Bootstrap 源代码分析(未完待续)
Bootstrap 是最受欢迎的 HTML、CSS 和 JS 框架,用于开发响应式布局、移动设备优先的 WEB 项目。——
Bootstrap 因为支持响应式布局、移动设备优先和易用易学等特点,使得它成为最受欢迎的前端开发框架。
Bootstrap 的响应式设计、组件开发和 JavaScript 插件开发和 预处理脚本的开发方法,也是值得学习的。
源代码
源代码下载和编译
推荐到 GitHub 下载最新、最全的 。
GitHub 是 Bootstrap 源代码托管仓库,不仅包含源代码,还包含 Bootstrap 使用文档的源文件。,可以在没有网络的情况下,可以通过 ,在本地机器上浏览文档。
源代码目录
包含
•文档部署代码子目录 _gh_pages/
•文档源代码子目录 docs/
•bootstrap 部署代码子目录 dist/
•bootstrap 脚本子目录 js/
•bootstrap 样式子目录 less/
•bootstrap 字体子目录 fonts/
•grunt 构建工具脚本子目录 grunt/
•包管理器 nuget 子目录 nuget/
•许多配置文件
切入点
Bootstrap 框架的源代码很复杂,要从作者开发框架的角度分析,无疑是很困难的。可以对问题进行简单化,不关注框架是怎么构建或部署的,只关注框架的工作原理,即 HTML、CSS/LESS 和 JS 部分。
通过 分治 的思想,把复杂的问题分解成许多简单的问题进行解决。当所有小问题都解决了,复杂的问题也就迎刃而解了。
把整个 Bootstrap框架分治成一个个组件,以组件为切入点,理解其工作原理,然后逐步分析整个框架。
组件分析
下拉菜单 dropdown
HTML代码
<!-- 组件下拉菜单 --> <div class="dropdown"> <!-- 触发按钮 --> <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown"> Dropdown <span class="caret"></span> </button> <!-- 下拉菜单 --> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> </ul> </div>
注意 代码中去除了源代码中的可访问属性aria-,便于分析。实际应用中不可省略。有关按钮样式这里也不展开进行分析
CSS代码
// Dropdown arrow/caret .caret { display: inline-block; width: 0; height: 0; margin-left: 2px; vertical-align: middle; border-: @caret-width-base dashed; border-: @caret-width-base solid ~"\9"; // IE8 border-right: @caret-width-base solid transparent; border-left: @caret-width-base solid transparent; } // The dropdown wrapper (div) .dropup, .dropdown { position: relative; // 父元素相对定位 } // Prevent the focus on the dropdown toggle when closing dropdowns .dropdown-toggle:focus { outline: 0; } // The dropdown menu (ul) .dropdown-menu { position: absolute; //子元素绝对定位 : 100%; // 下拉菜单紧贴父元素下边沿 left: 0; z-index: @zindex-dropdown; display: none; //默认隐藏,当触发按钮显示(display:block) float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; // override default ul list-style: none; font-size: @font-size-base; text-align: left; background-color: @dropdown-bg; border: 1px solid @dropdown-fallback-border; // IE8 fallback border: 1px solid @dropdown-border; border-radius: @border-radius-base; .box-shadow(0 6px 12px rgba(0,0,0,.175)); background-clip: padding-box; // Aligns the dropdown menu to right &.pull-right { right: 0; left: auto; } // 高度为1px的水平分隔线 .divider { .nav-divider(@dropdown-divider-bg); } // Links within the dropdown menu > li > a { display: block; padding: 3px 20px; clear: both; font-weight: normal; line-height: @line-height-base; color: @dropdown-link-color; white-space: nowrap; // 防止链接换行 } } // Hover/Focus state .dropdown-menu > li > a { &:hover, &:focus { text-decoration: none; color: @dropdown-link-hover-color; background-color: @dropdown-link-hover-bg; } } // Active state .dropdown-menu > .active > a { &, &:hover, &:focus { color: @dropdown-link-active-color; text-decoration: none; outline: 0; background-color: @dropdown-link-active-bg; } } // 显示下拉菜单 .open { > .dropdown-menu { display: block; // 显示 } // Remove the outline when :focus is triggered > a { outline: 0; } } // Menu positioning .dropdown-menu-right { left: auto; // Reset the default from `.dropdown-menu` right: 0; } // `.pull-right` nav ponent. .dropdown-menu-left { left: 0; right: auto; } // Dropdown section headers .dropdown-header { display: block; padding: 3px 20px; font-size: @font-size-small; line-height: @line-height-base; color: @dropdown-header-color; white-space: nowrap; // as with > li > a } // 非下拉菜单区域 .dropdown-backdrop { position: fixed; left: 0; right: 0; bottom: 0; : 0; z-index: (@zindex-dropdown - 10); //确保点击下拉菜单时,不会关闭下拉菜单 } // Right aligned dropdowns .pull-right > .dropdown-menu { right: 0; left: auto; } // Allow for dropdowns to go bottom up (aka, dropup-menu) // // Just add .dropup after the standard .dropdown class and you're set, bro. // TODO: abstract this so that the navbar fixed styles are not placed here? .dropup, .navbar-fixed-bottom .dropdown { // Reverse the caret .caret { border-: 0; border-bottom: @caret-width-base dashed; border-bottom: @caret-width-base solid ~"\9"; // IE8 content: ""; } // Different positioning for bottom up menu .dropdown-menu { : auto; bottom: 100%; margin-bottom: 2px; } } // Component alignment // // Reiterate per navbar.less and the modified ponent alignment there. @media (min-width: @grid-float-breakpoint) { .navbar-right { .dropdown-menu { .dropdown-menu-right(); } // Necessary for overrides of the default right aligned menu. // Will remove e v4 in all likelihood. .dropdown-menu-left { .dropdown-menu-left(); } } }
该下拉菜单组件的行为是当触发按钮被点击,在其下方显示下拉菜单,点击非下拉菜单区域时,隐藏下拉菜单。
实现原理
1.开始时只显示触发按钮,.dropdown包装默认下拉菜单关闭,.dropdown-menu默认隐藏 display:none
2.当触发按钮被点击,.dropdown后面添加类.open。在.open中 .dropdown-menu的display值是block。所以添加/删除.open类表示下拉菜单的显示/隐藏。
3.点击非下拉菜单区域时,.dropdown删除类.open,即隐藏下拉菜单。非下拉菜单区域的实现的原理是,固定定位,平铺,z-index比下拉菜单小,这样确保点击下拉菜单时,不会隐藏下拉菜单。
JavaScript代码
/ ======================================================================== Bootstrap: dropdown.js v3.3.6 http://getbootstrap./javascript/#dropdowns ======================================================================== Copyright 2011-2016 Twitter, Inc. Licensed under MIT (https://github./twbs/bootstrap/blob/master/LICENSE) ======================================================================== / +function ($) { 'use strict'; // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop' var toggle = '[data-toggle="dropdown"]' var Dropdown = function (element) { $(element).on('click.bs.dropdown', this.toggle) } Dropdown.VERSION = '3.3.6' function getParent($this) { var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.(?=#[^\s]$)/, '') // strip for ie7 } var $parent = selector && $(selector) return $parent && $parent.length ? $parent : $this.parent() } function clearMenus(e) { if (e && e.which === 3) return $(backdrop).remove() $(toggle).each(function () { var $this = $(this) var $parent = getParent($this) var relatedTarget = { relatedTarget: this } if (!$parent.hasClass('open')) return if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this.attr('aria-expanded', 'false') $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) }) } Dropdown.prototype.toggle = function (e) { var $this = $(this) if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') clearMenus() if (!isActive) { if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate $(document.createElement('div')) .addClass('dropdown-backdrop') .insertAfter($(this)) .on('click', clearMenus) } var relatedTarget = { relatedTarget: this } $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this .trigger('focus') .attr('aria-expanded', 'true') $parent .toggleClass('open') .trigger($.Event('shown.bs.dropdown', relatedTarget)) } return false } Dropdown.prototype.keydown = function (e) { if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) e.preventDefault() e.sPropagation() if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') if (!isActive && e.which != 27 || isActive && e.which == 27) { if (e.which == 27) $parent.find(toggle).trigger('focus') return $this.trigger('click') } var desc = ' li:not(.disabled):visible a' var $items = $parent.find('.dropdown-menu' + desc) if (!$items.length) return var index = $items.index(e.target) if (e.which == 38 && index > 0) index-- // up if (e.which == 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') } // DROPDOWN PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.dropdown') if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.dropdown $.fn.dropdown = Plugin $.fn.dropdown.Constructor = Dropdown // DROPDOWN NO CONFLICT // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old return this } // APPLY TO STANDARD DROPDOWN ELEMENTS // =================================== $(document) .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.sPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery);
Javascript代码结构可分为三个部分
1.类定义 1-125行
2.插件定义 126-144行
3.解决冲突 148-153行
4.应用到标准的下拉菜单元素 155-166行
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持狼蚁SEO。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程