# 5.折叠窗与手风琴

在使用前,请一定记得引入jQuery.js与bootstrap.js文件

# 5.1 折叠窗基本使用


<p>
  <!-- 通过a标签实现折叠窗触发 -->
  <!-- 折叠窗的触发器上,需要配置几个属性 -->
  <!-- data-toggle 属性,用于选择 切换 的事件——即以怎样的方式触发切换 -->
  <!-- 可选值有:modal , popover , tooltips , collapse 等 -->
  <!-- 折叠的效果,选择 collapse -->
  <!-- 在a标签中实现折叠窗,href属性指定的是折叠的内容,常用id表示 -->
  <a class="btn btn-primary" data-toggle="collapse" href="#collapseExample">
    折叠触发器a
  </a>
  <!-- 通过按钮实现折叠窗触发 -->
  <!-- 在按钮中,没法通过href属性指定折叠的内容,所以通过data-target来指定折叠的内容 -->
  <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample">
    折叠触发器btn
  </button>
</p>
<!-- 折叠的内容,需要配置 .collapse 类,来指明这是一个会被折叠的内容 -->
<!-- 同时需要配置id, id需要与触发器的 href的属性值 或 data-traget 的属性值 一致 -->
<div class="collapse" id="collapseExample">
  <div class="card card-body">
    折叠窗的内容
  </div>
</div>
<!-- 也可以通过data-target指定多个目标 -->
<p>
  <button data-toggle="collapse" data-target=".box1">折叠触发器btn</button>
</p>
<div class="collapse box1">
  <div>内容1</div>
</div>
<div class="collapse box1">
  <div>内容2</div>
</div>
<div class="collapse box1">
  <div>内容3</div>
</div>

# 5.2 手风琴的基本使用

要实现手风琴,需要使用 .accordion 类 包裹住 整个内容

配合卡片组件(.card)使用效果良好

<div class="accordion" id="accordionExample">
  <div class="card">
    <div class="card-header" id="headingOne">
      <h2 class="mb-0">
      <!-- aria-expanded属性设置其默认展开与否 -->
        <button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true">
          触发器1
        </button>
      </h2>
    </div>
    <div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
      <div class="card-body">
        折叠内容1
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingTwo">
      <h2 class="mb-0">
        <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseTwo"  >
          触发器2
        </button>
      </h2>
    </div>
    <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionExample">
      <div class="card-body">
        折叠内容2
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingThree">
      <h2 class="mb-0">
        <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseThree"  >
          触发器3
        </button>
      </h2>
    </div>
    <div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
      <div class="card-body">
        折叠内容3
      </div>
    </div>
  </div>
</div>
<!-- 简练化 -->
<div class="according" id="boxParent">
  <div>
    <button data-target="#box1" data-toggle="collapse" aria-expended="true">触发器1</button>
    <div class="collapse" id="box1" data-parent="#boxParent">内容1</div>
  </div>
  <div>
    <button data-target="#box2" data-toggle="collpase">触发器2</button>
    <div class="collapse" id="box2" data-parent="#boxParent">内容2</div>
  </div>
  <div>
    <button data-target="#box3" data-toggle="collapse">触发器3</button>
    <div class="collapse" id="box3" data-parent="#boxParent">内容3</div>
  </div>
</div>

# 5.3 源码分析

原本看了一些……但是发现实在太长了,所以先停了了……


var NAME$3 = 'collapse';
var VERSION$3 = '4.6.0';
var DATA_KEY$3 = 'bs.collapse';
var EVENT_KEY$3 = "." + DATA_KEY$3;
var DATA_API_KEY$3 = '.data-api';
var JQUERY_NO_CONFLICT$3 = $__default['default'].fn[NAME$3];
var Default$1 = {
	toggle: true,
	parent: ''
};
var DefaultType$1 = {
	toggle: 'boolean',
	parent: '(string|element)'
};
var EVENT_SHOW = "show" + EVENT_KEY$3;
var EVENT_SHOWN = "shown" + EVENT_KEY$3;
var EVENT_HIDE = "hide" + EVENT_KEY$3;
var EVENT_HIDDEN = "hidden" + EVENT_KEY$3;
var EVENT_CLICK_DATA_API$3 = "click" + EVENT_KEY$3 + DATA_API_KEY$3;
var CLASS_NAME_SHOW$1 = 'show';
var CLASS_NAME_COLLAPSE = 'collapse';
var CLASS_NAME_COLLAPSING = 'collapsing';
var CLASS_NAME_COLLAPSED = 'collapsed';
var DIMENSION_WIDTH = 'width';
var DIMENSION_HEIGHT = 'height';
var SELECTOR_ACTIVES = '.show, .collapsing';
var SELECTOR_DATA_TOGGLE$1 = '[data-toggle="collapse"]';

var Collapse = /*#__PURE__*/ function() {
	function Collapse(element, config) {
		this._isTransitioning = false;
		this._element = element;
		this._config = this._getConfig(config);
		// 两个选择器以保证a标签的href 和 data-target 都能获取到
		this._triggerArray = [].slice.call(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" +
			element
			.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]")));
		// 获取所有折叠元素对象,以数组的形式存储
		var toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$1));

		for (var i = 0, len = toggleList.length; i < len; i++) {
			var elem = toggleList[i];
			var selector = Util.getSelectorFromElement(elem);
			var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function(foundElem) {
				return foundElem === element;
			});

			if (selector !== null && filterElement.length > 0) {
				this._selector = selector;

				this._triggerArray.push(elem);
			}
		}

		this._parent = this._config.parent ? this._getParent() : null;

		if (!this._config.parent) {
			this._addAriaAndCollapsedClass(this._element, this._triggerArray);
		}

		if (this._config.toggle) {
			this.toggle();
		}
	} // Getters


	var _proto = Collapse.prototype;

	// Public
	_proto.toggle = function toggle() {
		if ($__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {
			this.hide();
		} else {
			this.show();
		}
	};

	_proto.show = function show() {
		var _this = this;

		if (this._isTransitioning || $__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {
			return;
		}

		var actives;
		var activesData;

		if (this._parent) {
			actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES)).filter(function(elem) {
				if (typeof _this._config.parent === 'string') {
					return elem.getAttribute('data-parent') === _this._config.parent;
				}

				return elem.classList.contains(CLASS_NAME_COLLAPSE);
			});

			if (actives.length === 0) {
				actives = null;
			}
		}

		if (actives) {
			activesData = $__default['default'](actives).not(this._selector).data(DATA_KEY$3);

			if (activesData && activesData._isTransitioning) {
				return;
			}
		}

		var startEvent = $__default['default'].Event(EVENT_SHOW);
		$__default['default'](this._element).trigger(startEvent);

		if (startEvent.isDefaultPrevented()) {
			return;
		}

		if (actives) {
			Collapse._jQueryInterface.call($__default['default'](actives).not(this._selector), 'hide');

			if (!activesData) {
				$__default['default'](actives).data(DATA_KEY$3, null);
			}
		}

		var dimension = this._getDimension();

		$__default['default'](this._element).removeClass(CLASS_NAME_COLLAPSE).addClass(CLASS_NAME_COLLAPSING);
		this._element.style[dimension] = 0;

		if (this._triggerArray.length) {
			$__default['default'](this._triggerArray).removeClass(CLASS_NAME_COLLAPSED).attr('aria-expanded',
				true);
		}

		this.setTransitioning(true);

		var complete = function complete() {
			$__default['default'](_this._element).removeClass(CLASS_NAME_COLLAPSING).addClass(
				CLASS_NAME_COLLAPSE + " " + CLASS_NAME_SHOW$1);
			_this._element.style[dimension] = '';

			_this.setTransitioning(false);

			$__default['default'](_this._element).trigger(EVENT_SHOWN);
		};

		var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
		var scrollSize = "scroll" + capitalizedDimension;
		var transitionDuration = Util.getTransitionDurationFromElement(this._element);
		$__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(
			transitionDuration);
		this._element.style[dimension] = this._element[scrollSize] + "px";
	};

	_proto.hide = function hide() {
		var _this2 = this;

		if (this._isTransitioning || !$__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {
			return;
		}

		var startEvent = $__default['default'].Event(EVENT_HIDE);
		$__default['default'](this._element).trigger(startEvent);

		if (startEvent.isDefaultPrevented()) {
			return;
		}

		var dimension = this._getDimension();

		this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
		Util.reflow(this._element);
		$__default['default'](this._element).addClass(CLASS_NAME_COLLAPSING).removeClass(CLASS_NAME_COLLAPSE +
			" " + CLASS_NAME_SHOW$1);
		var triggerArrayLength = this._triggerArray.length;

		if (triggerArrayLength > 0) {
			for (var i = 0; i < triggerArrayLength; i++) {
				var trigger = this._triggerArray[i];
				var selector = Util.getSelectorFromElement(trigger);

				if (selector !== null) {
					var $elem = $__default['default']([].slice.call(document.querySelectorAll(selector)));

					if (!$elem.hasClass(CLASS_NAME_SHOW$1)) {
						$__default['default'](trigger).addClass(CLASS_NAME_COLLAPSED).attr('aria-expanded',
							false);
					}
				}
			}
		}

		this.setTransitioning(true);

		var complete = function complete() {
			_this2.setTransitioning(false);

			$__default['default'](_this2._element).removeClass(CLASS_NAME_COLLAPSING).addClass(
				CLASS_NAME_COLLAPSE).trigger(EVENT_HIDDEN);
		};

		this._element.style[dimension] = '';
		var transitionDuration = Util.getTransitionDurationFromElement(this._element);
		$__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(
			transitionDuration);
	};

	_proto.setTransitioning = function setTransitioning(isTransitioning) {
		this._isTransitioning = isTransitioning;
	};

	_proto.dispose = function dispose() {
		$__default['default'].removeData(this._element, DATA_KEY$3);
		this._config = null;
		this._parent = null;
		this._element = null;
		this._triggerArray = null;
		this._isTransitioning = null;
	} // Private
	;

	_proto._getConfig = function _getConfig(config) {
		config = _extends({}, Default$1, config);
		config.toggle = Boolean(config.toggle); // Coerce string values

		Util.typeCheckConfig(NAME$3, config, DefaultType$1);
		return config;
	};

	_proto._getDimension = function _getDimension() {
		var hasWidth = $__default['default'](this._element).hasClass(DIMENSION_WIDTH);
		return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT;
	};

	_proto._getParent = function _getParent() {
		var _this3 = this;

		var parent;

		if (Util.isElement(this._config.parent)) {
			parent = this._config.parent; // It's a jQuery object

			if (typeof this._config.parent.jquery !== 'undefined') {
				parent = this._config.parent[0];
			}
		} else {
			parent = document.querySelector(this._config.parent);
		}

		var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]";
		var children = [].slice.call(parent.querySelectorAll(selector));
		$__default['default'](children).each(function(i, element) {
			_this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
		});
		return parent;
	};

	_proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
		var isOpen = $__default['default'](element).hasClass(CLASS_NAME_SHOW$1);

		if (triggerArray.length) {
			$__default['default'](triggerArray).toggleClass(CLASS_NAME_COLLAPSED, !isOpen).attr(
				'aria-expanded',
				isOpen);
		}
	} // Static
	;

	Collapse._getTargetFromElement = function _getTargetFromElement(element) {
		var selector = Util.getSelectorFromElement(element);
		return selector ? document.querySelector(selector) : null;
	};

	Collapse._jQueryInterface = function _jQueryInterface(config) {
		return this.each(function() {
			var $element = $__default['default'](this);
			var data = $element.data(DATA_KEY$3);

			var _config = _extends({}, Default$1, $element.data(), typeof config === 'object' &&
				config ? config : {});

			if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
				_config.toggle = false;
			}

			if (!data) {
				data = new Collapse(this, _config);
				$element.data(DATA_KEY$3, data);
			}

			if (typeof config === 'string') {
				if (typeof data[config] === 'undefined') {
					throw new TypeError("No method named \"" + config + "\"");
				}

				data[config]();
			}
		});
	};

	_createClass(Collapse, null, [{
		key: "VERSION",
		get: function get() {
			return VERSION$3;
		}
	}, {
		key: "Default",
		get: function get() {
			return Default$1;
		}
	}]);

	return Collapse;
}();


更新时间: 6/29/2021, 7:06:18 PM