Bootstrap简单认识之Collapse组件

来源:互联网 发布:古代皇帝的能力知乎 编辑:程序博客网 时间:2024/06/05 14:33

Collapse(内容折叠)组件

一、简介

此组件可以将一篇区域收起、展开,类似折叠的效果。主要用于内容过多时,将部分内容折叠。

二、样式

  1. 分析了这几个组件,发现Bootstrap喜欢将transition的持续时间设置为600ms
  2. 这个组件并没有什么特殊的样式,一共就几个:
.collapse {  display: none;  &.show {    display: block;  }}.collapsing {  position: relative;  height: 0;  overflow: hidden;  @include transition($transition-collapse);}

而card类貌似是取代了之前的panel,所以这里要使用card类包裹折叠元素,才能实现多个同类元素折叠相互影响的效果。

三、脚本

作用

  • 如果是单个组件,那就是用于控制指定元素折叠
  • 如果是多个组件一起,即某个元素展开就让其他元素折叠
  • 除了上述功能方面的控制,还有部分针对屏幕阅读器的属性控制(这里就暂且不提了)

代码梗概

class Collapse {  // 构造函数  constructor(element, config) {    // 正在 collapsing    this._isTransitioning = false    this._element         = element    this._config          = this._getConfig(config)    // 触发这个元素collapse的按钮    this._triggerArray    = $.makeArray($(      `[data-toggle="collapse"][href="#${element.id}"],` +      `[data-toggle="collapse"][data-target="#${element.id}"]`    ))    // 如果元素有 data-parent属性,表示有多个此类组件需要实现相互影响的折叠效果    // 这里除了获取了parent,还为同属于一个parent的多个同类组件按钮以及元素设置属性(包括自己)    // 同个parent下的被折叠元素,如果当前状态是展开,那么会被设置属性aria-expanded为true, 同时,其控制按钮的collapsed类会被移除(如果有的话)且aria-expanded属性也被设置为true;情况相反则以此类推(注意,collapsed类无属性)    this._parent = this._config.parent ? this._getParent() : null    // 如果只是单个组件活动,那么也为自己设置上述属性    if (!this._config.parent) {      this._addAriaAndCollapsedClass(this._element, this._triggerArray)    }    // 初始化的同时对元素折叠或是展开    // $('#myCollapsible').collapse({toggle: false})激活元素为collapse组件的同时不进行折叠或是展开    if (this._config.toggle) {      this.toggle()    }  }  // 展开  show() {}  // 折叠  hide() {}  // 外部接口  static _jQueryInterface(config) {}}$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {  event.preventDefault()  // 实例创建在被按钮控制的元素上  const target = Collapse._getTargetFromElement(this)  const data   = $(target).data(DATA_KEY)  // 如果已经实例化过,那么相当于调用$('xx').collapse('toggle')  // 否则,使用jquery data的属性实例化  const config = data ? 'toggle' : $(this).data()  Collapse._jQueryInterface.call($(target), config)})

代码中的注释有提到,实例创建在被控制的元素上,且实例一旦创建,只要不被销毁,实例就不会变化;由此可知,如果不是人为调用 $(xxx).data(DATA_KEY) 改变元素属性,实例配置一般就不变了。所以,如果使用js初始化一个实例,如果不传parent属性,即使在控制按钮上声明属性 data-parent="xxx" 也是相当于没有parent属性的。
主要也就是两个函数,其实还有个 toggle
函数,这里代码没贴出来,不过此函数就是通过判断元素是否有css show 类来调用 show 或是 hide 函数,在这里没有必要介绍。

function show
此函数作用是让元素展开,如果存在与其他同类组件,且通过 data-parent 需要相互影响,那么会在打开此元素的同时关闭其他元素

show() {  let actives  let activesData  // 如果有需要相互影响的元素,那么把他们找出来  if (this._parent) {    // 找寻同一个parent下的,所有已经展开或正在进行动画的元素(不是按钮)    // Selector.ACTIVES === '.card > .show, .card > .collapsing'    // 这里值得提一下,在之前的bootstrap版本中,我发现想要多个元素相互影响,需要具有 `.panel` 类,而在这个版本中,要的是 `card` 类,这是必须要的    actives = $.makeArray($(this._parent).find(Selector.ACTIVES))    if (!actives.length) {      actives = null    }  }  // 触发事件钩子,同其他组件一样,可以在此时阻止此函数继续执行  const startEvent = $.Event(Event.SHOW)  $(this._element).trigger(startEvent)  if (startEvent.isDefaultPrevented()) {    return  }  if (actives) {    // 关闭已经打开的元素    Collapse._jQueryInterface.call($(actives), 'hide')    // 如果原来此元素是没有Collapse实例在上面的,那么上一步生成的实例将被剔除    // 我猜是因为实例生成时没有读取配置的过程吧?    if (!activesData) {      $(actives).data(DATA_KEY, null)    }  }  // collapse类只有一个功能: display: none  // collapsing 则用于让元素具备动画属性  $(this._element)    .removeClass(ClassName.COLLAPSE)    .addClass(ClassName.COLLAPSING)  // 让高度为0(dimension === 'height')  this._element.style[dimension] = 0  this._element.setAttribute('aria-expanded', true)  // 为这个元素的按钮移除collapsed类(类无属性),标识对应元素已不再是collapsed状态  if (this._triggerArray.length) {    $(this._triggerArray)      .removeClass(ClassName.COLLAPSED)      .attr('aria-expanded', true)  }  // 动画开始  this.setTransitioning(true)  // 监听动画结束事件,这里不再分析  // 目前有了 collapsing类,即有了动画属性,这里设置 元素的 height = style.scrollHeight  // 设置动画结束后的钩子,内容是移除collapsing类,添加collapse和show类,两个类在一起时候只有一个作用: display: block  // 触发用户自定义事件钩子  this._element.style[dimension] = `${this._element[scrollSize]}px`}

从这里可以发现,想要实现多个此类组件相互影响的效果,必须为每个被折叠元素的外层套一个带有类 .card 的包装,这样才能被js捕捉到,如下:

<!--带card类--><div class="part card">    <h1><a href="#content-1" data-toggle='collapse' data-parent='#accordin'>        Toggle the Content-1    </a></h1>    <article id="content-1" class="collapse show">        ...    </article></div><div class="part card">    ...     </div><div class="part card">    ...     </div>

function hide
此函数相对于 show 函数要简单些,因为一个元素的关闭并不需要影响其他元素

hide() {  // 触发自定义事件钩子  const startEvent = $.Event(Event.HIDE)  $(this._element).trigger(startEvent)  if (startEvent.isDefaultPrevented()) {    return  }  // 让元素: style.height = style.offsetHeight  this._element.style[dimension] = `${this._element[offsetDimension]}px`  // 强制页面回流,避免js的  Util.reflow(this._element)  // 通过collapsing类添加动画效果  $(this._element)    .addClass(ClassName.COLLAPSING)    .removeClass(ClassName.COLLAPSE)    .removeClass(ClassName.SHOW)  this.setTransitioning(true)  // 设置height = 0 ,且注册动画结束钩子  this._element.style[dimension] = ''
0 0
原创粉丝点击