Ver código fonte

Tabs: fix dynamic bug & add closable prop for tab-pane (#1285)

FuryBean 8 anos atrás
pai
commit
f729497de5

+ 20 - 2
packages/tabs/src/tab-pane.vue

@@ -7,7 +7,8 @@
         type: String,
         required: true
       },
-      name: String
+      name: String,
+      closable: Boolean
     },
 
     data() {
@@ -17,14 +18,24 @@
         paneStyle: {
           position: 'relative'
         },
+        isClosable: null,
         index: ''
       };
     },
 
     created() {
+      const propsData = this.$options.propsData;
+      if (propsData && typeof propsData.closable !== 'undefined') {
+        this.isClosable = propsData.closable === '' || propsData.closable;
+      } else {
+        this.isClosable = this.$parent.closable;
+      }
       if (!this.index) {
         this.index = this.$parent.$children.indexOf(this) + 1 + '';
       }
+      if (this.$parent.panes) {
+        this.$parent.panes.push(this);
+      }
     },
 
     computed: {
@@ -34,9 +45,13 @@
     },
 
     destroyed() {
-      if (this.$el) {
+      if (this.$el && this.$el.parentNode) {
         this.$el.parentNode.removeChild(this.$el);
       }
+      const panes = this.$parent.panes;
+      if (panes) {
+        panes.splice(this, panes.indexOf(this));
+      }
     },
 
     watch: {
@@ -46,6 +61,9 @@
           this.index = val;
         }
       },
+      closable(val) {
+        this.isClosable = val;
+      },
       '$parent.currentName'(newValue, oldValue) {
         if (this.index === newValue) {
           this.transition = newValue > oldValue ? 'slideInRight' : 'slideInLeft';

+ 5 - 4
packages/tabs/src/tabs.vue

@@ -14,7 +14,8 @@
       return {
         children: null,
         activeTab: null,
-        currentName: 0
+        currentName: 0,
+        panes: []
       };
     },
 
@@ -80,7 +81,7 @@
     render(h) {
       let {
         type,
-        closable,
+        panes, // eslint-disable-line
         handleTabRemove,
         handleTabClick,
         currentName
@@ -103,14 +104,14 @@
             'el-tabs__item': true,
             'is-active': currentName === tab.index,
             'is-disabled': tab.disabled,
-            'is-closable': closable
+            'is-closable': tab.isClosable
           },
           ref: 'tabs',
           refInFor: true,
           on: { click: (ev) => { handleTabClick(tab, ev); } }
         }, [
           tab.label,
-          closable ? btnClose : null,
+          tab.isClosable ? btnClose : null,
           index === 0 ? activeBar : null
         ]);
         return _tab;

+ 20 - 17
packages/theme-default/src/tabs.css

@@ -35,6 +35,22 @@
       margin-bottom: -1px;
       position: relative;
 
+      & .el-icon-close {
+        border-radius: 50%;
+        text-align: center;
+        transition: all .3s cubic-bezier(.645,.045,.355,1);
+        margin-left: 5px;
+        &:before {
+          transform: scale(.7, .7);
+          display: inline-block;
+        }
+
+        &:hover {
+          background-color: #99a9bf;
+          color: #fff;
+        }
+      }
+
       @when active {
         color: var(--color-primary);
       }
@@ -53,29 +69,16 @@
         display: none;
       }
       & .el-tabs__item .el-icon-close {
+        position: relative;
         font-size: 12px;
+        width: 0;
+        height: 14px;
         vertical-align: middle;
         line-height: 15px;
         overflow: hidden;
-        width: 0;
-        height: 14px;
-        border-radius: 50%;
-        text-align: center;
-        transform-origin: 100% 50%;
-        transition: all .3s cubic-bezier(.645,.045,.355,1);
-        position: relative;
         top: -1px;
         right: -2px;
-
-        &:before {
-          transform: scale(.7, .7);
-          display: inline-block;
-        }
-
-        &:hover {
-          background-color: #99a9bf;
-          color: #fff;
-        }
+        transform-origin: 100% 50%;
       }
       .el-tabs__item {
         border: 1px solid transparent;

+ 55 - 0
test/unit/specs/tabs.spec.js

@@ -100,6 +100,44 @@ describe('Tabs', () => {
 
     expect(vm.$el.classList.contains('el-tabs--border-card')).to.be.true;
   });
+  it('dynamic', (done) => {
+    vm = createVue({
+      template: `
+        <el-tabs type="card" ref="tabs">
+          <el-tab-pane :label="tab.label" :name="tab.name" v-for="tab in tabs">Test Content</el-tab-pane>
+        </el-tabs>
+      `,
+      data() {
+        return {
+          tabs: [{
+            label: 'tab1',
+            name: 'tab1'
+          }, {
+            label: 'tab2',
+            name: 'tab2'
+          }, {
+            label: 'tab3',
+            name: 'tab3'
+          }, {
+            label: 'tab4',
+            name: 'tab4'
+          }]
+        };
+      }
+    }, true);
+
+    setTimeout(() => {
+      expect(vm.$el.querySelectorAll('.el-tab-pane').length).to.equal(4);
+      vm.tabs.push({
+        label: 'tab5',
+        name: 'tab5'
+      });
+      setTimeout(() => {
+        expect(vm.$el.querySelectorAll('.el-tab-pane').length).to.equal(5);
+        done();
+      });
+    }, 100);
+  });
   it('closable', done => {
     vm = createVue({
       template: `
@@ -130,6 +168,23 @@ describe('Tabs', () => {
       });
     }, 100);
   });
+  it('closable in tab-pane', (done) => {
+    vm = createVue({
+      template: `
+        <el-tabs type="card" ref="tabs">
+          <el-tab-pane label="用户管理" closable>A</el-tab-pane>
+          <el-tab-pane label="配置管理">B</el-tab-pane>
+          <el-tab-pane label="角色管理" closable>C</el-tab-pane>
+          <el-tab-pane label="定时任务补偿">D</el-tab-pane>
+        </el-tabs>
+      `
+    }, true);
+
+    setTimeout(() => {
+      expect(vm.$el.querySelectorAll('.el-icon-close').length).to.equal(2);
+      done();
+    }, 100);
+  });
   it('closable edge', done => {
     vm = createVue({
       template: `