Bladeren bron

fix collapse toggle bug (#2059)

baiyaaaaa 8 jaren geleden
bovenliggende
commit
d896c83860
3 gewijzigde bestanden met toevoegingen van 75 en 29 verwijderingen
  1. 30 23
      packages/collapse/src/collapse-item.vue
  2. 7 2
      packages/collapse/src/collapse.vue
  3. 38 4
      test/unit/specs/collapse.spec.js

+ 30 - 23
packages/collapse/src/collapse-item.vue

@@ -4,8 +4,8 @@
       <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">
+    <div class="el-collapse-item__wrap" ref="contentWrap">
+      <div class="el-collapse-item__content" ref="content">
         <slot></slot>
       </div>
     </div>
@@ -40,7 +40,10 @@
 
     data() {
       return {
-        contentStyle: {},
+        contentWrapStyle: {
+          height: 'auto',
+          display: 'block'
+        },
         contentHeight: 0
       };
     },
@@ -69,38 +72,42 @@
 
     methods: {
       open() {
-        const contentElm = this.$refs.content;
-        const contentStyle = this.contentStyle;
+        const contentWrapElm = this.$refs.contentWrap;
+        const contentHeight = this.contentHeight;
+
+        contentWrapElm.style.display = 'block';
+        contentWrapElm.style.height = '0';
 
-        contentStyle.display = 'block';
-        this.$nextTick(_ => {
-          contentStyle.height = this.contentHeight + 'px';
-          once(contentElm, getTransitionendEvent(contentElm), () => {
-            contentStyle.height = 'auto';
+        setTimeout(_ => {
+          contentWrapElm.style.height = contentHeight + 'px';
+          once(contentWrapElm, getTransitionendEvent(contentWrapElm), () => {
+            if (!this.isActive) return;
+            contentWrapElm.style.height = 'auto';
           });
-        });
+        }, 10);
       },
       close() {
+        const contentWrapElm = this.$refs.contentWrap;
         const contentElm = this.$refs.content;
-        const contentHeight = contentElm.clientHeight;
-        const contentStyle = this.contentStyle;
+        const contentHeight = contentElm.offsetHeight;
 
         this.contentHeight = contentHeight;
-        this.$set(this.contentStyle, 'height', contentHeight + 'px');
+        contentWrapElm.style.height = contentHeight + 'px';
 
-        this.$nextTick(_ => {
-          contentStyle.height = '0';
-          once(contentElm, getTransitionendEvent(contentElm), () => {
-            this.$set(this.contentStyle, 'display', 'none');
+        setTimeout(_ => {
+          contentWrapElm.style.height = '0';
+          once(contentWrapElm, getTransitionendEvent(contentWrapElm), () => {
+            if (this.isActive) return;
+            contentWrapElm.style.display = 'none';
           });
-        });
+        }, 10);
       },
       init() {
-        this.contentHeight = this.$refs.content.clientHeight;
-
         if (!this.isActive) {
-          this.$set(this.contentStyle, 'height', '0');
-          this.$set(this.contentStyle, 'display', 'none');
+          let contentWrapElm = this.$refs.contentWrap;
+          this.contentHeight = this.$refs.content.offsetHeight;
+          contentWrapElm.style.height = '0';
+          contentWrapElm.style.display = 'none';
         }
       },
       handleHeaderClick() {

+ 7 - 2
packages/collapse/src/collapse.vue

@@ -33,14 +33,19 @@
 
     methods: {
       setActiveNames(activeNames) {
+        activeNames = [].concat(activeNames);
         let value = this.accordion ? activeNames[0] : activeNames;
-        this.activeNames = [].concat(value);
+        this.activeNames = activeNames;
         this.$emit('input', value);
         this.$emit('change', value);
       },
       handleItemClick(item) {
         if (this.accordion) {
-          this.setActiveNames(this.activeNames[0] === item.name ? '' : item.name);
+          this.setActiveNames(
+            this.activeNames[0] &&
+            this.activeNames[0] === item.name
+            ? '' : item.name
+          );
         } else {
           let activeNames = this.activeNames.slice(0);
           let index = activeNames.indexOf(item.name);

+ 38 - 4
test/unit/specs/collapse.spec.js

@@ -35,16 +35,12 @@ describe('Collapse', () => {
         </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();
 
@@ -93,4 +89,42 @@ describe('Collapse', () => {
       done();
     });
   });
+
+  it('event:change', 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 spy = sinon.spy();
+    vm.$refs.collapse.$on('change', spy);
+    vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click();
+    vm.$nextTick(_ => {
+      expect(spy.withArgs().calledOnce).to.be.true;
+      done();
+    });
+  });
 });