Browse Source

feat: 新增tab组件

zhenyulei 5 years ago
parent
commit
be7bc65d5c
4 changed files with 416 additions and 294 deletions
  1. 120 105
      src/packages/tab/demo.vue
  2. 114 72
      src/packages/tab/doc.md
  3. 120 45
      src/packages/tab/tab.scss
  4. 62 72
      src/packages/tab/tab.vue

+ 120 - 105
src/packages/tab/demo.vue

@@ -1,25 +1,24 @@
 <template>
   <div>
     <!-- DEMO区域 -->
-    <h4>默认用法</h4>
+    <h4>基础样式</h4>
     <nut-tab @tab-switch="tabSwitch">
-      <nut-tab-panel tab-title="页签1">页签1</nut-tab-panel>
-      <nut-tab-panel tab-title="页签2">页签2</nut-tab-panel>
-      <nut-tab-panel tab-title="页签3">页签3</nut-tab-panel>
-      <nut-tab-panel tab-title="页签4">页签4</nut-tab-panel>
+        <nut-tab-panel tab-title="页签一">这里是页签1内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签二">这里是页签2内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签三">这里是页签3内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签四">这里是页签4内容</nut-tab-panel>
     </nut-tab>
 
-    <h4>支持导航条在上下左右位置</h4>
+    <h4>禁用样式</h4>
     <nut-tab @tab-switch="tabSwitch">
-      <nut-tab-panel
-        v-for="value in editableTabs"
-        v-bind:key="value.tabTitle"
-        :tab-title="value.tabTitle"
-        :icon-url="value.iconUrl"
-        v-html="value.content"
-      ></nut-tab-panel>
+        <nut-tab-panel tab-title="页签一">这里是页签1内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签二">这里是页签2内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签三" :disable="true">这里是页签3内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签四">这里是页签4内容</nut-tab-panel>
     </nut-tab>
-    <nut-tab @tab-switch="tabSwitch" position-nav="left">
+
+    <h4>超出界面宽度</h4>
+    <nut-tab @tab-switch="tabSwitch" :is-scroll="true">
       <nut-tab-panel
         v-for="value in editableTabs"
         v-bind:key="value.tabTitle"
@@ -28,17 +27,20 @@
         v-html="value.content"
       ></nut-tab-panel>
     </nut-tab>
-    <nut-tab @tab-switch="tabSwitch" position-nav="right">
+
+    <h4>纵向tab切换</h4>
+    <nut-tab @tab-switch="tabSwitch" position-nav="left" :wrapper-height="350">
       <nut-tab-panel
         v-for="value in editableTabs"
         v-bind:key="value.tabTitle"
         :tab-title="value.tabTitle"
-        :iconUrl="value.iconUrl"
+        :icon-url="value.iconUrl"
         v-html="value.content"
       ></nut-tab-panel>
     </nut-tab>
 
-    <nut-tab @tab-switch="tabSwitch" position-nav="bottom">
+    <h4>纵向tab切换超出界面高度,设置tab区域高度</h4>
+    <nut-tab @tab-switch="tabSwitch" position-nav="left" :is-scroll="true" :wrapper-height="200">
       <nut-tab-panel
         v-for="value in editableTabs"
         v-bind:key="value.tabTitle"
@@ -48,36 +50,21 @@
       ></nut-tab-panel>
     </nut-tab>
 
-    <h4>支持滑动选择多个页签</h4>
-    <nut-tab @tab-switch="tabSwitch" :is-scroll="true">
-      <nut-tab-panel tab-title="页签1">页签1</nut-tab-panel>
-      <nut-tab-panel tab-title="页签2">页签2</nut-tab-panel>
-      <nut-tab-panel tab-title="页签3">页签3</nut-tab-panel>
-      <nut-tab-panel tab-title="页签4">页签4</nut-tab-panel>
-      <nut-tab-panel tab-title="页签5">页签5</nut-tab-panel>
-      <nut-tab-panel tab-title="页签6">页签6</nut-tab-panel>
-      <nut-tab-panel tab-title="页签7">页签7</nut-tab-panel>
+    <h4>设置可以滑动的线段</h4>
+    <nut-tab @tab-switch="tabSwitch" :tab-line="false" :scroll-line="true">
+        <nut-tab-panel tab-title="页签一">这里是页签1内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签二">这里是页签2内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签三">这里是页签3内容</nut-tab-panel>
+        <nut-tab-panel tab-title="页签四">这里是页签4内容</nut-tab-panel>
     </nut-tab>
-
-    <h4>支持滑动选择多个页签</h4>
-    <nut-tab @tab-switch="tabSwitch" :is-scroll="true" position-nav="left">
-      <nut-tab-panel tab-title="页签1">页签1</nut-tab-panel>
-      <nut-tab-panel tab-title="页签2">页签2</nut-tab-panel>
-      <nut-tab-panel tab-title="页签3">页签3</nut-tab-panel>
-      <nut-tab-panel tab-title="页签4">页签4</nut-tab-panel>
-      <nut-tab-panel tab-title="页签5">页签5</nut-tab-panel>
-      <nut-tab-panel tab-title="页签6">页签6</nut-tab-panel>
-      <nut-tab-panel tab-title="页签7">页签7</nut-tab-panel>
-    </nut-tab>
-
-    <h4>禁止选中,默认选中某个标签</h4>
-    <h4>如需要更新页面,请将监听变化的数据传入init-data</h4>
-
-    <nut-tab :def-index="defIndex" class="customer-css" @tab-switch="tabSwitch" :contentShow="true" :init-data="disableTabs" :is-show-line="false">
+    
+    <h4>若更新页面,将监听变化的数据传入init-data</h4>
+    <nut-tab :def-index="defIndex" class="customer-css" :tab-line="false" @tab-switch="tabSwitch" :init-data="disableTabs"  :scroll-line="true">
       <nut-tab-panel
         v-for="value in disableTabs"
         v-bind:key="value.tabTitle"
         :tab-title="value.tabTitle"
+        :icon-url="value.iconUrl"
         :disable="value.disable"
         v-html="value.content"
       ></nut-tab-panel>
@@ -91,112 +78,140 @@
 
 <script>
 export default {
-  components: {},
+  components:{
+  },
   data() {
     return {
-      defIndex: 1,
-      positionNavCurr: 'top',
+      defIndex:1,
+      positionNavCurr: "top",
       editableTabs: [
         {
-          tabTitle: '衣物',
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
-          content: '<p>衣物内容</p>'
+          tabTitle: "推荐分类",
+          iconUrl: "",
+          content: "<p>这里是推荐分类内容</p>"
+        },
+        {
+          tabTitle: "家电清洗",
+          iconUrl: "",
+          content: "<p>这里是家电清洗内容</p>"
+        },
+        {
+          tabTitle: "箱包养护",
+          iconUrl: "",
+          content: "<p>这里是箱包养护内容</p>"
         },
         {
-          tabTitle: '日用品',
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg',
-          content: '<p>日用品内容</p>'
+          tabTitle: "屏幕换新",
+          iconUrl: "",
+          content: "<p>这里是屏幕换新内容</p>"
         },
         {
-          tabTitle: '器材',
-          iconUrl: 'http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg',
-          content: '<p>运动器材内容</p>'
+          tabTitle: "电池换新",
+          iconUrl: "",
+          content: "<p>这里是电池换新内容</p>"
         },
         {
-          tabTitle: '电影票',
-          iconUrl: 'http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg',
-          content: '<p>电影票内容</p>'
+          tabTitle: "内存升级",
+          iconUrl: "",
+          content: "<p>这里是内存升级内容</p>"
+        },
+        {
+          tabTitle: "家电服务",
+          iconUrl: "",
+          content: "<p>这里是家电服务内容</p>"
         }
       ],
       disableTabs: [
         {
-          tabTitle: '衣物',
-          disable: false,
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
-          content: '<p>衣物内容</p>'
+          tabTitle: "衣物",
+          disable:true,
+          iconUrl:
+            "http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg",
+          content: "<p>衣物内容</p>"
         },
         {
-          tabTitle: '日用品',
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg',
-          content: '<p>日用品内容</p>'
+          tabTitle: "日用品",
+          iconUrl:
+            "http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg",
+          content: "<p>日用品内容</p>"
         },
         {
-          tabTitle: '运动器材',
-          iconUrl: 'http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg',
-          content: '<p>运动器材内容</p>'
+          tabTitle: "运动器材",
+          iconUrl:
+            "http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg",
+          content: "<p>运动器材内容</p>"
         },
         {
-          tabTitle: '电影票',
-          iconUrl: 'http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg',
-          content: '<p>电影票内容</p>'
+          tabTitle: "电影票",
+          iconUrl:
+            "http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg",
+          content: "<p>电影票内容</p>"
         }
       ]
     };
   },
   methods: {
     tabSwitch: function(index, event) {
-      console.log(index + '--' + event);
+      console.log(index + "--" + event);
       //this.defIndex = index;
     },
-    clickHandler: function() {
+    clickHandler:function(){
       let newEditableTabs = [
         {
-          tabTitle: '衣物2',
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
-          content: '<p>改变衣物内容</p>'
+          tabTitle: "衣物2",
+          iconUrl:
+            "http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg",
+          content: "<p>改变衣物内容</p>"
         },
         {
-          tabTitle: '日用品2',
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg',
-          content: '<p>改变日用品内容</p>'
+          tabTitle: "日用品2",
+          iconUrl:
+            "http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg",
+          content: "<p>改变日用品内容</p>"
         },
         {
-          tabTitle: '器材2',
-          iconUrl: 'http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg',
-          content: '<p>改变运动器材内容</p>'
+          tabTitle: "器材2",
+          iconUrl:
+            "http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg",
+          content: "<p>改变运动器材内容</p>"
         },
         {
-          tabTitle: '电影票2',
-          iconUrl: 'http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg',
-          content: '<p>改变电影票内容</p>'
+          tabTitle: "电影票2",
+          iconUrl:
+            "http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg",
+          content: "<p>改变电影票内容</p>"
         }
-      ];
+      ]
       this.disableTabs = newEditableTabs;
     },
-    resetHandler: function() {
-      let newEditableTabs = [
-        {
-          tabTitle: '衣物',
-          disable: false,
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
-          content: '<p>衣物内容</p>'
+    resetHandler:function(){
+        let newEditableTabs = [
+        {
+          tabTitle: "衣物",
+          disable: true,
+          iconUrl:
+            "http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg",
+          content: "<p>衣物内容</p>"
         },
         {
-          tabTitle: '日用品',
-          iconUrl: 'http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg',
-          content: '<p>日用品内容</p>'
+          tabTitle: "日用品",
+          iconUrl:
+            "http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg",
+          content: "<p>日用品内容</p>"
         },
         {
-          tabTitle: '运动器材',
-          iconUrl: 'http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg',
-          content: '<p>运动器材内容</p>'
+          tabTitle: "运动器材",
+          iconUrl:
+            "http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg",
+          content: "<p>运动器材内容</p>"
         },
         {
-          tabTitle: '电影票',
-          iconUrl: 'http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg',
-          content: '<p>电影票内容</p>'
+          tabTitle: "电影票",
+          iconUrl:
+            "http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg",
+          content: "<p>电影票内容</p>"
         }
-      ];
+      ]
       this.disableTabs = newEditableTabs;
     }
   }
@@ -206,17 +221,16 @@ export default {
 <style lang="scss">
 .customer-css {
   .nut-tab-active .nut-tab-link {
-    color: #fff;
+    color: #E1251B;
   }
   .nut-title-nav-list {
     background: #fff;
     border-left: 1px solid #e4e7ed;
-    &:first-child {
+    &:first-child{
       border-left: 0;
     }
   }
   .nut-tab-active {
-    background: $primary-color;
     border: 0;
     transition: all 0.3s ease-in-out;
   }
@@ -228,3 +242,4 @@ export default {
   }
 }
 </style>
+

+ 114 - 72
src/packages/tab/doc.md

@@ -1,18 +1,19 @@
 # Tab 选项卡
 
-常用于平级区域大块内容的的收纳和展现。
+常用于平级区域大块内容的的收纳和展现,支持内嵌标签形式和渲染循环数据形式
 
 > 注意,使用该组件需要在引入 nut-tab-panel 组件
 
 `import { TabPanel } from "@nutui/nutui";`
 
-## 基本用法
+## 基础样式
 
 ```html
 <nut-tab @tab-switch="tabSwitch">
-    <nut-tab-panel tab-title="页签1">页签1</nut-tab-panel>
-    <nut-tab-panel tab-title="页签2">页签2</nut-tab-panel>
-    <nut-tab-panel tab-title="页签3">页签3</nut-tab-panel>
+    <nut-tab-panel tab-title="页签一">这里是页签1内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签二">这里是页签2内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签三">这里是页签3内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签四">这里是页签4内容</nut-tab-panel>
 </nut-tab>
 ```
 ```javascript
@@ -25,97 +26,135 @@ export default {
 };
 ```
 
-## 使用数据渲染,支持上/下/左/右四个样式;
+## 禁用样式:
 
 ```html
-<nut-tab @tab-switch="tabSwitch"  position-nav="bottom">
-    <nut-tab-panel 
-      v-for="value in editableTabs" 
-      v-bind:key="value.tabTitle" 
-      :tab-title="value.tabTitle" 
-      :icon-url="value.tabUrl" 
-      v-html="value.content"
-    >
-    </nut-tab-panel>
+<nut-tab @tab-switch="tabSwitch">
+    <nut-tab-panel tab-title="页签一">这里是页签1内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签二">这里是页签2内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签三" :disable="true">这里是页签3内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签四">这里是页签4内容</nut-tab-panel>
+</nut-tab>
+```
+
+## 超出界面宽度
+```html
+<nut-tab @tab-switch="tabSwitch" :is-scroll="true">
+  <nut-tab-panel
+    v-for="value in editableTabs"
+    v-bind:key="value.tabTitle"
+    :tab-title="value.tabTitle"
+    :icon-url="value.iconUrl"
+    v-html="value.content"
+  ></nut-tab-panel>
 </nut-tab>
 ```
 ```javascript
 export default {
   data() {
-    return {
-      positionNavCurr:'top',
-      editableTabs:[
-        {
-          'tabTitle':'衣物',
-          'tabUrl':'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
-          'content':'<p>衣物内容</p>'
-        },
-        {
-          'tabTitle':'日用品',
-          'tabUrl':'http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg',
-          'content':'<p>日用品内容</p>'
-        },
-        {
-          'tabTitle':'器材',
-          'tabUrl':'http://img20.360buyimg.com/uba/jfs/t30346/262/553689202/2257/5dfa3983/5bf76407N72deabf4.jpg',
-          'content':'<p>运动器材内容</p>'
-        },
-        {
-          'tabTitle':'电影票',
-          'tabUrl':'http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg',
-          'content':'<p>电影票内容</p>'
-        }
-      ]
-    };
-  },
-  methods: {
-      tabSwitch:function(index,event){
-        console.log(index+'--'+event);
+      return {
+          editableTabs: [
+          {
+            tabTitle: "推荐分类",
+            iconUrl: "",
+            content: "<p>这里是推荐分类内容</p>"
+          },
+          {
+            tabTitle: "家电清洗",
+            iconUrl: "",
+            content: "<p>这里是家电清洗内容</p>"
+          },
+          {
+            tabTitle: "箱包养护",
+            iconUrl: "",
+            content: "<p>这里是箱包养护内容</p>"
+          },
+          {
+            tabTitle: "屏幕换新",
+            iconUrl: "",
+            content: "<p>这里是屏幕换新内容</p>"
+          },
+          {
+            tabTitle: "电池换新",
+            iconUrl: "",
+            content: "<p>这里是电池换新内容</p>"
+          },
+          {
+            tabTitle: "内存升级",
+            iconUrl: "",
+            content: "<p>这里是内存升级内容</p>"
+          },
+          {
+            tabTitle: "家电服务",
+            iconUrl: "",
+            content: "<p>这里是家电服务内容</p>"
+          }
+        ]
       }
   }
 };
 ```
-## 支持滑动选择多个页签
+
+## 纵向tab切换
 
 ```html
-  <nut-tab @tab-switch="tabSwitch" :is-scroll="true">
-      <nut-tab-panel tab-title="页签1">页签1</nut-tab-panel>
-      <nut-tab-panel tab-title="页签2">页签2</nut-tab-panel>
-      <nut-tab-panel tab-title="页签3">页签3</nut-tab-panel>
-      <nut-tab-panel tab-title="页签4">页签4</nut-tab-panel>
-      <nut-tab-panel tab-title="页签5">页签5</nut-tab-panel>
-      <nut-tab-panel tab-title="页签6">页签6</nut-tab-panel>
-      <nut-tab-panel tab-title="页签7">页签7</nut-tab-panel>
-  </nut-tab>
+<nut-tab @tab-switch="tabSwitch" position-nav="left" :wrapper-height="350">
+  <nut-tab-panel
+    v-for="value in editableTabs"
+    v-bind:key="value.tabTitle"
+    :tab-title="value.tabTitle"
+    :icon-url="value.iconUrl"
+    v-html="value.content"
+  ></nut-tab-panel>
+</nut-tab>
 ```
 
+## 纵向tab切换超出界面高度,设置tab区域高度
+
 ```html
-  <nut-tab @tab-switch="tabSwitch" :is-scroll="true" position-nav="left">
-      <nut-tab-panel tab-title="页签1">页签1</nut-tab-panel>
-      <nut-tab-panel tab-title="页签2">页签2</nut-tab-panel>
-      <nut-tab-panel tab-title="页签3">页签3</nut-tab-panel>
-      <nut-tab-panel tab-title="页签4">页签4</nut-tab-panel>
-      <nut-tab-panel tab-title="页签5">页签5</nut-tab-panel>
-      <nut-tab-panel tab-title="页签6">页签6</nut-tab-panel>
-      <nut-tab-panel tab-title="页签7">页签7</nut-tab-panel>
-  </nut-tab>
+<nut-tab @tab-switch="tabSwitch" position-nav="left" :is-scroll="true" :wrapper-height="200">
+  <nut-tab-panel
+    v-for="value in editableTabs"
+    v-bind:key="value.tabTitle"
+    :tab-title="value.tabTitle"
+    :icon-url="value.iconUrl"
+    v-html="value.content"
+  ></nut-tab-panel>
+</nut-tab>
 ```
 
-## 禁止选中,默认选中某个标签,如需更新数组后,重新渲染Tab页面,请将更新数组传入init-data
+## 设置可以滑动的线段
+
+```html
+<nut-tab @tab-switch="tabSwitch" :tab-line="false" :scroll-line="true">
+    <nut-tab-panel tab-title="页签一">这里是页签1内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签二">这里是页签2内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签三">这里是页签3内容</nut-tab-panel>
+    <nut-tab-panel tab-title="页签四">这里是页签4内容</nut-tab-panel>
+</nut-tab>
+```
 
+## 若更新页面,将监听变化的数据传入init-data,且可以自定义class类名,样式覆盖
 ```html
-<nut-tab :def-index="1" class="customer-css" @tab-switch="tabSwitch" :contentShow="true" :init-data="disableTabs">
-    <nut-tab-panel
+<nut-tab 
+  :def-index="defIndex" 
+  class="customer-css" 
+  :tab-line="false" 
+  @tab-switch="tabSwitch" 
+  :init-data="disableTabs"  
+  :scroll-line="true">
+  <nut-tab-panel
     v-for="value in disableTabs"
     v-bind:key="value.tabTitle"
     :tab-title="value.tabTitle"
+    :icon-url="value.iconUrl"
     :disable="value.disable"
     v-html="value.content"
   ></nut-tab-panel>
 </nut-tab>
 <div style="width:100%;height=50px;text-align:center">
-  <Button @click="resetHandler" type="light">重置Tab页面</Button>
-  <Button @click="clickHandler">更新Tab页面</Button>
+  <nut-button @click="resetHandler" type="light">重置Tab页面</nut-button>
+  <nut-button @click="clickHandler">更新Tab页面</nut-button>
 </div>
 ```
 
@@ -128,7 +167,7 @@ export default {
       disableTabs:[
         {
           'tabTitle':'衣物',
-          'disable':false,
+          'disable':true,
           'tabUrl':'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
           'content':'<p>衣物内容</p>'
         },
@@ -187,7 +226,7 @@ export default {
           let newEditableTabs = [
           {
             tabTitle: "衣物",
-            disable: false,
+            disable: true,
             iconUrl:
               "http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg",
             content: "<p>衣物内容</p>"
@@ -227,8 +266,11 @@ export default {
 | position-nav | 页签栏的分布,可选值 top/bottom/left/right | String | top
 | def-index | 默认选中的页签栏 | String | 1
 | init-data | 监听数据变化,渲染更新页面 | Array | []
-| is-show-line|是否显示tab切换时的红条|Boolean|true|
-| is-scroll|是否支持滑动选择多个页签|Boolean|false|
+| scroll-line|是否显示tab切换时,滑动效果的红条|Boolean|false|
+| tab-line|是否显示tab切换时,无滑动效果的active红条|Boolean|true|
+| is-scroll|是否支持超出范围后,滑动选择多个页签|Boolean|false|
+| wrapper-height |设置tab区域的高度,只有在 is-scroll=true;positionNav=left或者right 的情况下有效|Number/String|200|
+
 
 ### nut-tab-panel
 

+ 120 - 45
src/packages/tab/tab.scss

@@ -1,9 +1,5 @@
-.nut-tab {
-  position: relative;
-  border: 1px solid #eee;
-  padding: 10px;
-  font-size: 12px;
-  background: #eee;
+.nut-tab-part{
+  margin-bottom: 20px;
 }
 .nut-tab-horizontal {
   display: flex;
@@ -39,22 +35,45 @@
   top: 0px;
   border-radius: 50%;
 }
-.nut-tab-title {
+.nut-tab-title-topnav {
   //border:1px solid #fff;
   border-bottom: 1px solid #ededed;
+  scroll-behavior: smooth;
   width: 100%;
   display: flex;
-  height: 50px;
+  height: 48px;
   line-height: 48px;
   box-sizing: border-box;
   position: relative;
   overflow-x: auto;
   overflow-y: hidden;
   &::-webkit-scrollbar {
-    display: none;
+      display: none;
+  }
+  .nut-tab-active {
+    background: #fff;
+    position: relative;
+    border: 0;
+    .nut-tab-link{
+        color: #E1251B;
+        font-weight: bold;
+    }
+    .tab-line{
+      &:after{
+        content: "";
+        position: absolute;
+        width: 30%;
+        transform: translateX(-50%);
+        height: 2px;
+        background: #E1251B;
+        bottom: 0px;
+        left: 50%;
+        z-index: 20;
+      }
+    }
   }
 }
-.nav-bar {
+.nav-bar-top {
   position: absolute;
   height: 2px;
   bottom: 0px;
@@ -64,17 +83,17 @@
   transition: all 0.3s ease-in-out;
 }
 .nut-tab-title-leftnav {
-  border-right: 1px solid #ededed;
-  width: 100px;
+  border-right: 1px solid #fff;
+  scroll-behavior: smooth;
+  width: 90px;
   display: flex;
-  background: #fff;
   flex-direction: column;
   position: relative;
-  height: 200px;
+  // height: 200px;
   overflow-y: auto;
   overflow-x: hidden;
   &::-webkit-scrollbar {
-    display: none;
+      display: none;
   }
   .nav-bar-left {
     position: absolute;
@@ -87,42 +106,76 @@
   }
   .nut-title-nav {
     border: 0;
+    background: #F7F7F7;
     border-left: 1px solid #f5f7fa;
   }
   .nut-tab-active {
-    background: #fff;
-    //   a{
-    //     color: red;
-    //   }
+    .nut-tab-link{
+      position: relative;
+      background: #fff;
+      color: #E1251B;
+      font-weight: bold;
+    }
+    .tab-line{
+      &:after{
+        content: "";
+        position: absolute;
+        height: 100%;
+        width: 3px;
+        background: #E1251B;
+        left: 0px;
+        top: 0;
+        z-index: 2;
+      }
+    }
   }
 }
 .nut-tab-title-rightnav {
-  background: #fff;
+  background: #F7F7F7;
   // border: 1px solid #fff;
-  border-left: 1px solid #ededed;
+  scroll-behavior: smooth;
+  border-left: 1px solid #fff;
   width: 100px;
   display: flex;
   flex-direction: column;
   position: relative;
   overflow-y: auto;
   overflow-x: hidden;
-  height: 200px;
   box-sizing: border-box;
   &::-webkit-scrollbar {
-    display: none;
+      display: none;
   }
   .nav-bar-right {
     position: absolute;
     width: 2px;
     left: 0px;
     top: 0px;
-    z-index: 2;
-    background: $primary-color;
+    background: #E1251B;
+    z-index:2;
     transition: all 0.3s ease-in-out;
   }
+  .nut-tab-active {
+    .nut-tab-link{
+      background: #fff;
+      color: #E1251B;
+      font-weight: bold;
+    }
+    .tab-line{
+      &:after{
+        content: "";
+        position: absolute;
+        height: 100%;
+        width: 3px;
+        background: #E1251B;
+        right: 0px;
+        top: 0;
+        z-index: 2;
+      }
+    }
+  }
 }
 .nut-tab-link {
-  color: #333;
+  color: #969696;
   display: flex;
   align-items: center;
   justify-content: center;
@@ -130,21 +183,23 @@
   text-decoration: none;
   line-height: 1;
   width: 100%;
-  height: 100%;
+  height:100%;
+  font-size: 13px;
 }
 .nut-tab-title-bottomnav {
   border: 1px solid #fff;
+  scroll-behavior: smooth;
   border-top: 1px solid #ededed;
   width: 100%;
   display: flex;
-  height: 50px;
-  line-height: 49px;
+  height: 48px;
+  line-height: 48px;
   box-sizing: border-box;
   position: relative;
   overflow-x: auto;
   overflow-y: hidden;
   &::-webkit-scrollbar {
-    display: none;
+      display: none;
   }
   .nav-bar-bottom {
     position: absolute;
@@ -155,9 +210,31 @@
     background: $primary-color;
     transition: all 0.3s ease-in-out;
   }
+  .nut-tab-active {
+    background: #fff;
+    position: relative;
+    border: 0;
+    .nut-tab-link{
+        color: #E1251B;
+        font-weight: bold;
+    }
+    .tab-line{
+      &:after{
+        content: "";
+        position: absolute;
+        width: 30%;
+        transform: translateX(-50%);
+        height: 2px;
+        background: #E1251B;
+        top: 0px;
+        left: 50%;
+        z-index: 20;
+      }
+    }
+  }
 }
 
-.nut-title-nav-list {
+.nut-title-nav-topnav,.nut-title-nav-bottomnav{
   flex: 1;
   position: relative;
   flex-direction: row;
@@ -183,7 +260,7 @@
   align-items: center;
   position: relative;
 }
-.nut-title-nav-scroll {
+.nut-title-nav-scroll{
   min-width: 100px;
   position: relative;
   flex-direction: row;
@@ -193,14 +270,13 @@
   background: #fff;
   box-sizing: border-box;
 }
-.nut-title-vertical-scroll {
-  min-height: 55px;
+.nut-title-vertical-scroll{
+  min-height: 50px;
   position: relative;
   flex-direction: row;
   align-items: center;
   justify-content: center;
   display: flex;
-  background: #fff;
   box-sizing: border-box;
 }
 .nut-tab-icon {
@@ -211,26 +287,25 @@
   background-repeat: no-repeat;
   background-size: 100% 100%;
 }
-.nut-tab-active {
-  background: #fff;
-  border: 0;
-  // a{
-  //     color: red;
-  // }
-}
+
 .nut-tab-item {
-  height: 200px;
+  height: 88px;
   border: 1px solid #fff;
   background: #fff;
   width: 100%;
-  padding: 10px;
+  padding: 20px;
   box-sizing: border-box;
+  font-size: 14px;
+  color: #646464;
   .hide {
     display: none;
   }
 }
 .nut-tab-disable {
-  background: #e1e1e1 !important;
+  .nut-tab-link{
+    color: #C8C8C8 !important;
+    font-size: 15px;
+  }
 }
 .tabbar-nav-word {
   font-size: $font-size-small;

+ 62 - 72
src/packages/tab/tab.vue

@@ -1,23 +1,23 @@
 <template>
   <div class="nut-tab-part">
     <div class="nut-tab" :class="{ 'nut-tab-horizontal': positionNavCss }">
-      <div v-if="positionNav == 'right' || positionNav == 'bottom'" class="nut-tab-item" ref="items">
+      <div v-if="positionNav == 'right' || positionNav == 'bottom'" class="nut-tab-item" ref="items" :style="customHeight">
         <slot></slot>
       </div>
-      <div :class="titleClass" ref="navlist">
-        <b v-if="isShowLine" :class="navBarClass" :style="navBarStyle"></b>
-        <span
-          v-for="(value, index) in tabTitleList"
-          :key="index"
-          :class="[titleNavList, 'nut-title-nav', { 'nut-tab-disable': value.disable }, { 'nut-tab-active': activeIndex == index }]"
-        >
-          <a class="nut-tab-link" v-on:click="switchTab(index, $event, value.disable)">
-            <i class="nut-tab-icon" :style="{ backgroundImage: 'url(' + value.iconUrl + ')' }" v-if="value.iconUrl"></i>
-            {{ value.tabTitle }}
-          </a>
-        </span>
+      <div :class="titleClass"  ref="navlist" :style="customHeight">
+          <b v-if="scrollLine" :class="navBarClass" :style="navBarStyle"></b>
+          <span
+            v-for="(value, index) in tabTitleList"
+            :key="index"
+            :class="[titleNavList, 'nut-title-nav', { 'nut-tab-disable': value.disable }, { 'nut-tab-active': activeIndex == index }]"
+          >
+            <span class="nut-tab-link" v-on:click="switchTab(index, $event, value.disable)" :class="{'tab-line':tabLine}">
+              <i  v-if="value.iconUrl" class="nut-tab-icon" :style="{ backgroundImage: 'url(' + value.iconUrl + ')' }"></i>
+              {{ value.tabTitle }}
+            </span>
+          </span>
       </div>
-      <div v-if="positionNav == 'top' || positionNav == 'left'" class="nut-tab-item" ref="items">
+      <div v-if="positionNav == 'top' || positionNav == 'left'" class="nut-tab-item" ref="items" :style="customHeight">
         <slot></slot>
       </div>
     </div>
@@ -27,11 +27,15 @@
 export default {
   name: 'nut-tab',
   props: {
-    isScroll: {
+    isScroll:{
+        type:Boolean,
+        default:false
+    },
+    scrollLine: {
       type: Boolean,
       default: false
     },
-    isShowLine: {
+    tabLine:{
       type: Boolean,
       default: true
     },
@@ -48,14 +52,19 @@ export default {
       default: function() {
         return [];
       }
+    },
+    wrapperHeight:{
+      type: [String,Number],
+      default: '200'
     }
   },
   data() {
     return {
       tabTitleList: [],
       activeIndex: this.defIndex,
-      initX: '0',
-      navWidth: 0
+      initX: 0,
+      navWidth: 0,
+      tapWidth:0
     };
   },
   watch: {
@@ -70,52 +79,47 @@ export default {
     }
   },
   computed: {
-    //下面有些样式名称是为了兼容之前的版本
     positionNavCss: function() {
       if (this.positionNav === 'left' || this.positionNav === 'right') return true;
     },
     titleClass: function() {
-      if (this.positionNav == 'top') {
-        return 'nut-tab-title';
-      }
       return 'nut-tab-title-' + this.positionNav + 'nav';
     },
     navBarClass: function() {
-      if (this.positionNav == 'top') {
-        return 'nav-bar';
-      }
       return 'nav-bar-' + this.positionNav;
     },
     titleNavList: function() {
       if (this.positionNav == 'top' || this.positionNav == 'bottom') {
-        if (this.isScroll) {
-          return 'nut-title-nav-scroll';
-        }
-        return 'nut-title-nav-list';
-      } else {
-        if (this.isScroll) {
-          return 'nut-title-vertical-scroll';
-        }
-        return 'nut-title-nav-' + this.positionNav + 'nav';
+        if(this.isScroll) return 'nut-title-nav-scroll';
+      }else{
+        if(this.isScroll) return 'nut-title-vertical-scroll';
       }
+      return 'nut-title-nav-' + this.positionNav + 'nav';
     },
     navBarStyle: function() {
       if (this.positionNav === 'top' || this.positionNav === 'bottom') {
-        return {
-          transform: `translateX(${this.initX}px)`,
-          width: this.navWidth + 'px'
-        };
+          return {
+            transform: `translateX(${this.initX}px)`,
+            width: this.navWidth + 'px'
+          };
       }
       return {
-        transform: `translateY(${this.initX}px)`,
-        height: this.navWidth + 'px'
+          transform: `translateY(${this.initX}px)`,
+          height: this.navWidth + 'px'
       };
+    },
+    customHeight:function(){
+      if(this.positionNav === 'left' || this.positionNav === 'right'){
+        return {
+          height:this.wrapperHeight+'px'
+        }
+      }else{
+        return null;
+      }
     }
   },
   mounted() {
-    this.$nextTick(() => {
-      this.$slots.default && this.updeteTab(this.$slots.default);
-    });
+    this.$slots.default && this.updeteTab(this.$slots.default);
   },
   methods: {
     updeteTab: function() {
@@ -130,9 +134,10 @@ export default {
         let slotTag = slot[i].tag;
         if (typeof slotTag == 'string' && slotTag.indexOf('nut-tab-panel') != -1) {
           let attrs = slot[i].data.attrs;
+          console.log(attrs.disable);
           let item = {
             tabTitle: attrs['tab-title'] || attrs['tabTitle'],
-            disable: attrs.disable === false,
+            disable: attrs.disable === true,
             iconUrl: attrs['iconUrl'] || attrs['icon-url']
           };
           this.tabTitleList.push(item);
@@ -146,41 +151,27 @@ export default {
         }
       }
       this.$nextTick(() => {
+        let tapWidth;
         if (this.positionNav == 'top' || this.positionNav == 'bottom') {
-          this.navWidth = this.$refs.navlist.querySelector('.nut-title-nav').offsetWidth;
-        } else {
-          this.navWidth = this.$refs.navlist.querySelector('.nut-title-nav').offsetHeight;
+            this.navWidth = this.$refs.navlist.querySelector('.nut-title-nav').offsetWidth;
+            tapWidth = this.$refs.navlist.offsetWidth;
+        }else{
+            this.navWidth = this.$refs.navlist.querySelector('.nut-title-nav').offsetHeight;
+            tapWidth = this.$refs.navlist.offsetHeight;
         }
         this.initX = parseInt(this.navWidth * this.defIndex);
+        this.tapWidth = tapWidth/2-this.navWidth/2;
       });
     },
-    getStyle: function(obj, styleName) {
-      if (!obj) {
-        return '';
-      }
-      if (obj.currentStyle) {
-        return obj.currentStyle[styleName];
-      } else {
-        return getComputedStyle(obj, null)[styleName];
-      }
-    },
-    findParent(event, myclass) {
-      let parentCpt = event.target;
-      let flag = 0; //避免死循环
-      while (parentCpt && flag < 10) {
-        flag++;
-        if (parentCpt.className && parentCpt.className === myclass) {
-          break;
-        }
-        parentCpt = parentCpt.parentNode;
-      }
-      return parentCpt;
-    },
     switchTab: function(index, event, disable) {
       if (!disable) {
         this.activeIndex = index;
-        this.initX = parseInt(this.navWidth * index);
-        let nutTab = this.findParent(event, 'nut-tab-part');
+        this.initX = parseInt(this.navWidth * index); 
+        if(this.positionNav == 'top' || this.positionNav == 'bottom'){
+            this.$refs.navlist.scroll(this.initX-this.tapWidth,0);
+        }else{
+            this.$refs.navlist.scroll(0, this.initX-this.tapWidth);
+        }   
         let items = this.$refs.items.children;
         for (let i = 0; i < items.length; i++) {
           if (i == index) {
@@ -190,7 +181,6 @@ export default {
           }
         }
         this.$emit('tab-switch', index, event);
-        this.$emit('tabSwitch', index, event); //兼容以前驼峰法命名
       }
     }
   }