Browse Source

add collapse

baiyaaaaa 8 years ago
parent
commit
46295dfd92

+ 3 - 1
components.json

@@ -55,5 +55,7 @@
   "steps": "./packages/steps/index.js",
   "step": "./packages/step/index.js",
   "carousel": "./packages/carousel/index.js",
-  "carousel-item": "./packages/carousel-item/index.js"
+  "carousel-item": "./packages/carousel-item/index.js",
+  "collapse": "./packages/collapse/index.js",
+  "collapse-item": "./packages/collapse-item/index.js"
 }

+ 150 - 0
examples/docs/en-US/collapse.md

@@ -0,0 +1,150 @@
+<script>
+  export default {
+    data() {
+      return {
+        activeNames: ['1'],
+        activeName: '1'
+      };
+    },
+    methods: {
+      handleChange(val) {
+        console.log(val);
+      }
+    }
+  }
+</script>
+<style>
+  .demo-collapse {
+    .el-collapse-item__header {
+      .header-icon {
+        margin-left: 5px;
+      }
+    }
+  }
+</style>
+
+## Collapse
+
+Use Collapse to storage content.
+
+### Basic usage
+
+可同时展开多个面板,面板之间不影响
+
+:::demo
+```html
+<el-collapse v-model="activeNames" @change="handleChange">
+  <el-collapse-item title="Consistency" name="1">
+    <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+    <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Feedback" name="2">
+    <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+    <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Efficiency" name="3">
+    <div>简化流程:设计简洁直观的操作流程;</div>
+    <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+    <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Controllability" name="4">
+    <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+    <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+  </el-collapse-item>
+</el-collapse>
+<script>
+  export default {
+    data() {
+      return {
+        activeNames: ['1']
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Accordion
+
+At the same time only one item can be opened.
+
+:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。
+```html
+<el-collapse v-model="activeName" accordion>
+  <el-collapse-item title="Consistency" name="1">
+    <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+    <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Feedback" name="2">
+    <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+    <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Efficiency" name="3">
+    <div>简化流程:设计简洁直观的操作流程;</div>
+    <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+    <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Controllability" name="4">
+    <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+    <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+  </el-collapse-item>
+</el-collapse>
+<script>
+  export default {
+    data() {
+      return {
+        activeName: '1'
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Customize Title
+
+除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。
+
+:::demo
+```html
+<el-collapse accordion>
+  <el-collapse-item title="Consistency">
+    <template slot="title" scope="props">
+      {{props.title}}<i class="header-icon el-icon-information"></i>
+    </template>
+    <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+    <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Feedback">
+    <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+    <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Efficiency">
+    <div>简化流程:设计简洁直观的操作流程;</div>
+    <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+    <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+  </el-collapse-item>
+  <el-collapse-item title="Controllability">
+    <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+    <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+  </el-collapse-item>
+</el-collapse>
+```
+:::
+
+### Collapse Attributes
+| Attribute      | Description          | Type      | Accepted Values       | Default  |
+|---------- |-------------- |---------- |--------------------------------  |-------- |
+| accordion | whether is accordion mode | boolean | — | false |
+| value | the active item's name | string/array | — | — |
+
+### Collapse Events
+| Event Name | Description | Parameters |
+|---------|---------|---------|
+| change | trigger when the active names change | (activeNames: array) |
+
+### Collapse Item Attributes
+| Attribute      | Description          | Type      | Accepted Values       | Default  |
+|---------- |-------------- |---------- |--------------------------------  |-------- |
+| name | unique identifier | string/number | — | — |
+| title | title | string | — | — |

+ 150 - 0
examples/docs/zh-CN/collapse.md

@@ -0,0 +1,150 @@
+<script>
+  export default {
+    data() {
+      return {
+        activeNames: ['1'],
+        activeName: '1'
+      };
+    },
+    methods: {
+      handleChange(val) {
+        console.log(val);
+      }
+    }
+  }
+</script>
+<style>
+  .demo-collapse {
+    .el-collapse-item__header {
+      .header-icon {
+        margin-left: 5px;
+      }
+    }
+  }
+</style>
+
+## Collapse 折叠面板
+
+通过折叠面板收纳内容区域
+
+### 基础用法
+
+可同时展开多个面板,面板之间不影响
+
+:::demo
+```html
+<el-collapse v-model="activeNames" @change="handleChange">
+  <el-collapse-item title="一致性 Consistency" name="1">
+    <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+    <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+  </el-collapse-item>
+  <el-collapse-item title="反馈 Feedback" name="2">
+    <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+    <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+  </el-collapse-item>
+  <el-collapse-item title="效率 Efficiency" name="3">
+    <div>简化流程:设计简洁直观的操作流程;</div>
+    <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+    <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+  </el-collapse-item>
+  <el-collapse-item title="可控 Controllability" name="4">
+    <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+    <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+  </el-collapse-item>
+</el-collapse>
+<script>
+  export default {
+    data() {
+      return {
+        activeNames: ['1']
+      };
+    }
+  }
+</script>
+```
+:::
+
+### 手风琴效果
+
+每次只能展开一个面板
+
+:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。
+```html
+<el-collapse v-model="activeName" accordion>
+  <el-collapse-item title="一致性 Consistency" name="1">
+    <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+    <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+  </el-collapse-item>
+  <el-collapse-item title="反馈 Feedback" name="2">
+    <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+    <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+  </el-collapse-item>
+  <el-collapse-item title="效率 Efficiency" name="3">
+    <div>简化流程:设计简洁直观的操作流程;</div>
+    <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+    <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+  </el-collapse-item>
+  <el-collapse-item title="可控 Controllability" name="4">
+    <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+    <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+  </el-collapse-item>
+</el-collapse>
+<script>
+  export default {
+    data() {
+      return {
+        activeName: '1'
+      };
+    }
+  }
+</script>
+```
+:::
+
+### 自定义面板标题
+
+除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。
+
+:::demo
+```html
+<el-collapse accordion>
+  <el-collapse-item title="一致性 Consistency">
+    <template slot="title" scope="props">
+      {{props.title}}<i class="header-icon el-icon-information"></i>
+    </template>
+    <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+    <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+  </el-collapse-item>
+  <el-collapse-item title="反馈 Feedback">
+    <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+    <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+  </el-collapse-item>
+  <el-collapse-item title="效率 Efficiency">
+    <div>简化流程:设计简洁直观的操作流程;</div>
+    <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+    <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+  </el-collapse-item>
+  <el-collapse-item title="可控 Controllability">
+    <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+    <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+  </el-collapse-item>
+</el-collapse>
+```
+:::
+
+### Collapse Attributes
+| 参数      | 说明          | 类型      | 可选值                           | 默认值  |
+|---------- |-------------- |---------- |--------------------------------  |-------- |
+| accordion | 是否手风琴模式 | boolean | — | false |
+| value | 当前激活的面板 | string/array | — | — |
+
+### Collapse Events
+| 事件名称 | 说明 | 回调参数 |
+|---------|---------|---------|
+| change | 当前激活面板改变时触发 | (activeNames: array) |
+
+### Collapse Item Attributes
+| 参数      | 说明          | 类型      | 可选值                           | 默认值  |
+|---------- |-------------- |---------- |--------------------------------  |-------- |
+| name | 唯一标志符 | string/number | — | — |
+| title | 面板标题 | string | — | — |

+ 8 - 0
examples/nav.config.json

@@ -211,6 +211,10 @@
             {
               "path": "/carousel",
               "title": "Carousel 走马灯"
+            },
+            {
+              "path": "/collapse",
+              "title": "Collapse 折叠面板"
             }
           ]
         }
@@ -429,6 +433,10 @@
             {
               "path": "/carousel",
               "title": "Carousel"
+            },
+            {
+              "path": "/collapse",
+              "title": "Collapse"
             }
           ]
         }

+ 8 - 0
packages/collapse-item/index.js

@@ -0,0 +1,8 @@
+import ElCollapseItem from '../collapse/src/collapse-item.vue';
+
+/* istanbul ignore next */
+ElCollapseItem.install = function(Vue) {
+  Vue.component(ElCollapseItem.name, ElCollapseItem);
+};
+
+export default ElCollapseItem;

+ 13 - 0
packages/collapse/_index.js

@@ -0,0 +1,13 @@
+import ElCollapse from './src/collapse';
+import ElCollapseItem from './src/collapse-item.vue';
+
+/* istanbul ignore next */
+export default function install(Vue) {
+  Vue.component(ElCollapseItem.name, ElCollapseItem);
+  Vue.component(ElCollapse.name, ElCollapse);
+};
+
+export {
+  ElCollapse,
+  ElCollapseItem
+};

+ 18 - 0
packages/collapse/cooking.conf.js

@@ -0,0 +1,18 @@
+var cooking = require('cooking');
+var path = require('path');
+var config = require('../../build/config');
+
+cooking.set({
+  entry: {
+    index: path.join(__dirname, '_index.js')
+  },
+  dist: path.join(__dirname, 'lib'),
+  template: false,
+  format: 'umd',
+  moduleName: 'ElCollapse',
+  extends: ['vue2'],
+  alias: config.alias,
+  externals: { vue: config.vue }
+});
+
+module.exports = cooking.resolve();

+ 9 - 0
packages/collapse/index.js

@@ -0,0 +1,9 @@
+import ElCollapse from './src/collapse';
+
+/* istanbul ignore next */
+ElCollapse.install = function(Vue) {
+  Vue.component(ElCollapse.name, ElCollapse);
+};
+
+export default ElCollapse;
+

+ 15 - 0
packages/collapse/package.json

@@ -0,0 +1,15 @@
+{
+  "name": "element-collapse",
+  "version": "1.0.0",
+  "description": "A row component for Vue.",
+  "keywords": [
+    "element",
+    "vue",
+    "component"
+  ],
+  "main": "./lib/index.js",
+  "repository": "https://github.com/ElemeFE/element/tree/master/packages/collapse",
+  "author": "haiping.zeng@ele.me",
+  "license": "MIT",
+  "dependencies": {}
+}

+ 106 - 0
packages/collapse/src/collapse-item.vue

@@ -0,0 +1,106 @@
+<template>
+  <div class="el-collapse-item" :class="{'is-active': isActive}">
+    <div class="el-collapse-item__header" @click="handleHeaderClick">
+      <i class="el-collapse-item__header__arrow el-icon-arrow-right"></i>
+      <slot name="title" :title="title">{{title}}</slot>
+    </div>
+    <div class="el-collapse-item__wrap" ref="content" :style="contentStyle">
+      <div class="el-collapse-item__content">
+        <slot></slot>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  import { once } from 'wind-dom';
+  import Emitter from 'element-ui/src/mixins/emitter';
+
+  function uid() {
+    function S4() {
+      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+    }
+    return `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;
+  }
+
+  export default {
+    name: 'ElCollapseItem',
+
+    componentName: 'ElCollapseItem',
+
+    mixins: [Emitter],
+
+    data() {
+      return {
+        contentStyle: {},
+        contentHeight: 0
+      };
+    },
+
+    props: {
+      title: String,
+      name: {
+        type: [String, Number],
+        default() {
+          return uid();
+        }
+      }
+    },
+
+    computed: {
+      isActive() {
+        return this.$parent.activeNames.indexOf(this.name) > -1;
+      }
+    },
+
+    watch: {
+      'isActive'(value) {
+        value ? this.open() : this.close();
+      }
+    },
+
+    methods: {
+      open() {
+        const contentElm = this.$refs.content;
+        const contentStyle = this.contentStyle;
+
+        contentStyle.display = 'block';
+        this.$nextTick(_ => {
+          contentStyle.height = this.contentHeight + 'px';
+          once(contentElm, 'transitionend', () => {
+            contentStyle.height = 'auto';
+          });
+        });
+      },
+      close() {
+        const contentElm = this.$refs.content;
+        const contentHeight = contentElm.clientHeight;
+        const contentStyle = this.contentStyle;
+
+        this.contentHeight = contentHeight;
+        this.$set(this.contentStyle, 'height', contentHeight + 'px');
+
+        this.$nextTick(_ => {
+          contentStyle.height = '0';
+          once(contentElm, 'transitionend', () => {
+            this.$set(this.contentStyle, 'display', 'none');
+          });
+        });
+      },
+      init() {
+        this.contentHeight = this.$refs.content.clientHeight;
+
+        if (!this.isActive) {
+          this.$set(this.contentStyle, 'height', '0');
+          this.$set(this.contentStyle, 'display', 'none');
+        }
+      },
+      handleHeaderClick() {
+        this.dispatch('ElCollapse', 'item-click', this);
+      }
+    },
+
+    mounted() {
+      this.init();
+    }
+  };
+</script>

+ 62 - 0
packages/collapse/src/collapse.vue

@@ -0,0 +1,62 @@
+<template>
+  <div class="el-collapse">
+    <slot></slot>
+  </div>
+</template>
+<script>
+  export default {
+    name: 'ElCollapse',
+
+    componentName: 'ElCollapse',
+
+    props: {
+      accordion: Boolean,
+      value: {
+        type: [Array, String],
+        default() {
+          return [];
+        }
+      }
+    },
+
+    data() {
+      return {
+        activeNames: [].concat(this.value)
+      };
+    },
+
+    watch: {
+      value(value) {
+        this.activeNames = [].concat(value);
+      }
+    },
+
+    methods: {
+      setActiveNames(activeNames) {
+        let value = this.accordion ? activeNames[0] : activeNames;
+        this.activeNames = [].concat(value);
+        this.$emit('input', value);
+        this.$emit('change', value);
+      },
+      handleItemClick(item) {
+        if (this.accordion) {
+          this.setActiveNames(this.activeNames[0] === item.name ? '' : item.name);
+        } else {
+          let activeNames = this.activeNames.slice(0);
+          let index = activeNames.indexOf(item.name);
+
+          if (index > -1) {
+            activeNames.splice(index, 1);
+          } else {
+            activeNames.push(item.name);
+          }
+          this.setActiveNames(activeNames);
+        }
+      }
+    },
+
+    created() {
+      this.$on('item-click', this.handleItemClick);
+    }
+  };
+</script>

+ 0 - 0
packages/theme-default/src/collapse-item.css


+ 52 - 0
packages/theme-default/src/collapse.css

@@ -0,0 +1,52 @@
+@charset "UTF-8";
+@import "./common/var.css";
+
+@component-namespace el {
+  @b collapse {
+    border: 1px solid var(--collapse-border-color);
+    border-radius: var(--collapse-border-radius);
+  }
+  @b collapse-item {
+    @e header {
+      height: var(--collapse-header-height);
+      line-height: @height;
+      padding-left: 15px;
+      background-color: var(--collapse-header-fill);
+      color: var(--collapse-header-color);
+      cursor: pointer;
+      border-bottom: 1px solid var(--collapse-border-color);
+      font-size: var(--collapse-header-size);
+
+      @e arrow {
+        margin-right: 8px;
+        transition: transform .3s;
+      }
+    }
+
+    @e wrap {
+      will-change: height;
+      background-color: var(--collapse-content-fill);
+      transition: height .3s cubic-bezier(0.215, 0.61, 0.355, 1);
+      overflow: hidden;
+      box-sizing: border-box;
+      border-bottom: 1px solid var(--collapse-border-color);
+    }
+
+    @e content {
+      padding: 10px 15px;
+      font-size: var(--collapse-content-size);
+      color: var(--collapse-content-color);
+      line-height: 1.769230769230769;
+    }
+
+    @when active {
+      .el-collapse-item__header__arrow {
+        transform: rotate(90deg);
+      }
+    }
+
+    &:last-child {
+      margin-bottom: -1px;
+    }
+  }
+}

+ 13 - 0
packages/theme-default/src/common/var.css

@@ -556,4 +556,17 @@
   --carousel-indicator-padding-horizontal: 4px;
   --carousel-indicator-padding-vertical: 12px;
   --carousel-indicator-out-color: var(--border-color-hover);
+
+  /* Collapse
+  --------------------------*/
+  --collapse-border-color: #e0e6ed;
+  --collapse-header-height: 43px;
+  --collapse-border-radius: 0;
+  --collapse-header-padding: 20px;
+  --collapse-header-fill: #fff;
+  --collapse-header-color: #475669;
+  --collapse-header-size: 13px;
+  --collapse-content-fill: #f9fafc;
+  --collapse-content-size: 13px;
+  --collapse-content-color: #1f2d3d;
 }

+ 1 - 0
packages/theme-default/src/index.css

@@ -42,3 +42,4 @@
 @import "./step.css";
 @import "./carousel.css";
 @import "./carousel-item.css";
+@import "./collapse.css";

+ 7 - 1
src/index.js

@@ -57,6 +57,8 @@ import Steps from '../packages/steps';
 import Step from '../packages/step';
 import Carousel from '../packages/carousel';
 import CarouselItem from '../packages/carousel-item';
+import Collapse from '../packages/collapse';
+import CollapseItem from '../packages/collapse-item';
 import locale from 'element-ui/src/locale';
 
 const install = function(Vue, opts = {}) {
@@ -117,6 +119,8 @@ const install = function(Vue, opts = {}) {
   Vue.component(Step.name, Step);
   Vue.component(Carousel.name, Carousel);
   Vue.component(CarouselItem.name, CarouselItem);
+  Vue.component(Collapse.name, Collapse);
+  Vue.component(CollapseItem.name, CollapseItem);
 
   Vue.use(Loading.directive);
 
@@ -194,5 +198,7 @@ module.exports = {
   Steps,
   Step,
   Carousel,
-  CarouselItem
+  CarouselItem,
+  Collapse,
+  CollapseItem
 };

+ 96 - 0
test/unit/specs/collapse.spec.js

@@ -0,0 +1,96 @@
+import { createVue, destroyVM } from '../util';
+
+describe('Collapse', () => {
+  let vm;
+  afterEach(() => {
+    destroyVM(vm);
+  });
+
+  it('create', done => {
+    vm = createVue({
+      data() {
+        return {
+          activeNames: ['1']
+        };
+      },
+      template: `
+        <el-collapse v-model="activeNames" ref="collapse">
+          <el-collapse-item title="一致性 Consistency" name="1" ref="item1">
+            <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+            <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+          </el-collapse-item>
+          <el-collapse-item title="反馈 Feedback" name="2">
+            <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+            <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+          </el-collapse-item>
+          <el-collapse-item title="效率 Efficiency" name="3" ref="item3">
+            <div>简化流程:设计简洁直观的操作流程;</div>
+            <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+            <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+          </el-collapse-item>
+          <el-collapse-item title="可控 Controllability" name="4">
+            <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+            <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+          </el-collapse-item>
+        </el-collapse>
+      `
+    }, true);
+    const collapse = vm.$refs.collapse;
+    const spy = sinon.spy();
+
+    collapse.$on('change', spy);
+    expect(vm.$refs.item1.isActive).to.be.true;
+    vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click();
+    vm.$nextTick(_ => {
+      expect(vm.$refs.item1.isActive).to.be.true;
+      expect(vm.$refs.item3.isActive).to.be.true;
+      expect(spy.calledOnce).to.be.true;
+
+      vm.$refs.item1.$el.querySelector('.el-collapse-item__header').click();
+
+      vm.$nextTick(_ => {
+        expect(vm.$refs.item1.isActive).to.be.false;
+        done();
+      });
+    });
+  });
+
+  it('accordion', done => {
+    vm = createVue({
+      data() {
+        return {
+          activeNames: ['1']
+        };
+      },
+      template: `
+        <el-collapse accordion v-model="activeNames" ref="collapse">
+          <el-collapse-item title="一致性 Consistency" name="1" ref="item1">
+            <div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
+            <div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
+          </el-collapse-item>
+          <el-collapse-item title="反馈 Feedback" name="2">
+            <div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
+            <div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
+          </el-collapse-item>
+          <el-collapse-item title="效率 Efficiency" name="3" ref="item3">
+            <div>简化流程:设计简洁直观的操作流程;</div>
+            <div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
+            <div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
+          </el-collapse-item>
+          <el-collapse-item title="可控 Controllability" name="4">
+            <div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
+            <div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
+          </el-collapse-item>
+        </el-collapse>
+      `
+    }, true);
+
+    expect(vm.$refs.item1.isActive).to.be.true;
+    vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click();
+    vm.$nextTick(_ => {
+      expect(vm.$refs.item1.isActive).to.be.false;
+      expect(vm.$refs.item3.isActive).to.be.true;
+      done();
+    });
+  });
+});