Browse Source

Merge branch 'v2' of https://github.com/jdf2e/nutui into v2

yewenwen 5 years ago
parent
commit
2f5886bd7b

+ 44 - 0
src/packages/avatar/__test__/avatar.spec.js

@@ -0,0 +1,44 @@
+import { shallowMount, mount } from '@vue/test-utils'
+import avatar from '../avatar.vue'
+import Vue from 'vue';
+
+
+describe('Avatar.vue', () => {
+    const wrapper = shallowMount(avatar, {
+    });
+    it('尺寸规格', () => {
+        wrapper.setProps({size: "small" });
+        return Vue.nextTick().then(function () {
+            expect(wrapper.find('.nut-avatar').contains('.avatar-small')).toBe(true);
+        })
+    });
+
+    it('形状类型是否为square', () => {
+        wrapper.setProps({shape: "square" });
+        return Vue.nextTick().then(function () {
+            expect(wrapper.find('.nut-avatar').contains('.avatar-square')).toBe(true);
+        })
+    });
+
+    it('背景颜色是否为red', () => {
+        wrapper.setProps({bgColor: "red" });
+        return Vue.nextTick().then(function () {
+            expect(wrapper.find('.nut-avatar').hasStyle('background-color','red')).toBe(true);
+        })
+    });
+
+    it('背景图片是否为设置的bgImage', () => {
+        wrapper.setProps({bgImage: "http://image.png" });
+        return Vue.nextTick().then(function () {
+            // console.log(wrapper.find('.nut-avatar').attributes('style'))
+            expect(wrapper.find('.nut-avatar').hasStyle('background-image','url(http://image.png)')).toBe(true);
+        })
+    });
+
+    it('头像图片是否为设置的bgIcon', () => {
+        wrapper.setProps({bgIcon: "http://image.png" });
+        return Vue.nextTick().then(function () {
+            expect(wrapper.find('.icon').hasStyle('background-image','url(http://image.png)')).toBe(true);
+        })
+    });
+});

+ 0 - 18
src/packages/avatar/avatar.scss

@@ -21,24 +21,6 @@
         text-align: center;
         overflow: hidden;
     }
-    .dot{
-        position: absolute;
-        min-width: 18px;
-        min-height: 18px;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        padding: 2px;
-        text-align: center;
-        border-radius: 50%;
-        background:red;
-        top:-4px;
-        right: -5px;
-        color: #fff;
-        font-size: 12px;
-        transform: scale(0.8);
-        line-height: 1;
-    }
 }
 .avatar-large{
     width: 40px;

+ 9 - 8
src/packages/avatar/avatar.vue

@@ -1,7 +1,7 @@
 <template>
     <div :style="styles" :class="['nut-avatar', 'avatar-'+size,'avatar-'+shape]" @click="activeAvatar">
-        <i class="icon" :style="iconStyles"></i>
-        <span class="text"><slot></slot></span>
+        <i class="icon" :style="iconStyles"></i><!--不使用icon组件,1:icon组件没有扩展维护;2:修改该图片不方便-->
+        <span class="text" v-if="isShowText"><slot></slot></span>
     </div>
 </template>
 <script>
@@ -32,14 +32,15 @@ export default {
     computed:{
         styles(){
             return {
-                'background':`${this.bgColor} url(${this.bgImage}) no-repeat`,
-                'backgroundSize':'100%'
+                'backgroundImage':this.bgImage?`url(${this.bgImage})`:null,
+                'backgroundColor':`${this.bgColor}`
             }
         },
         iconStyles(){
-            return {
-                'backgroundImage': `url(${this.bgIcon})`
-            }
+            return this.bgIcon?{'backgroundImage': `url(${this.bgIcon})`}:null;
+        },
+        isShowText(){
+            return this.$slots.default;
         }
     },
     data() {
@@ -47,7 +48,7 @@ export default {
     },
     methods: {
         activeAvatar(){
-            this.$emit('active-avatar');
+            this.$emit('active-avatar',event);
         }
     }
 }

+ 2 - 2
src/packages/avatar/demo.vue

@@ -48,8 +48,8 @@ export default {
     return {};
   },
   methods: {
-    activeAvatar() {
-      alert("点击了头像");
+    activeAvatar(event) {
+      console.log("点击了头像",event);
     }
   }
 };

+ 6 - 1
src/packages/avatar/doc.md

@@ -61,7 +61,12 @@
 | size | 设置头像的大小,提供三种:large /normal/small | String | normal
 | shape | 设置头像的形状,默认是圆形,可以设置为square方形 | String | round
 | bg-image | 设置头像的背景图片 | String | --
-| bg-icon | 设置头像的icon图标 | String | --
+| bg-icon | 设置头像的icon图标 | String | 默认based64格式的头像图片
+
+## slot
+| 字段 | 说明 |
+|--|--|
+|--|用户自定义icon或者文字|
 
 
 ## Event

+ 3 - 6
src/packages/tab/demo.vue

@@ -58,17 +58,15 @@
       ></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>
   </div>
 </template>
 
 <script>
-import Button from '../button/button.vue';
 export default {
   components:{
-    Button
   },
   data() {
     return {
@@ -131,7 +129,7 @@ export default {
   },
   methods: {
     tabSwitch: function(index, event) {
-      console.log(index + "--" + event.target);
+      console.log(index + "--" + event);
       //this.defIndex = index;
     },
     clickHandler:function(){
@@ -201,7 +199,6 @@ export default {
 .customer-css {
   .nut-tab-active .nut-tab-link {
     color: #fff;
-    transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
   }
   .nut-title-nav-list {
     background: #fff;

+ 7 - 3
src/packages/tab/doc.md

@@ -2,6 +2,10 @@
 
 常用于平级区域大块内容的的收纳和展现。
 
+> 注意,使用该组件需要在引入 nut-tab-panel 组件
+
+`import { TabPanel } from "@nutui/nutui";`
+
 ## 基本用法
 
 ```html
@@ -15,7 +19,7 @@
 export default {
   methods: {
       tabSwitch:function(index,event){
-        console.log(index+'--'+event.target);
+        console.log(index+'--'+event);
       }
   }
 };
@@ -66,7 +70,7 @@ export default {
   },
   methods: {
       tabSwitch:function(index,event){
-        console.log(index+'--'+event.target);
+        console.log(index+'--'+event);
       }
   }
 };
@@ -198,7 +202,7 @@ export default {
 | position-nav | 页签栏的分布,可选值 top/bottom/left/right | String | top
 | def-index | 默认选中的页签栏 | String | 1
 | init-data | 监听数据变化,渲染更新页面 | Array | []
-
+| is-show-line|是否显示tab切换时的红条|true|
 
 
 ### nut-tab-panel

+ 81 - 105
src/packages/tab/tab.vue

@@ -1,78 +1,25 @@
 <template>
-    <div v-if='showTabs'>
+    <div class="nut-tab-part" >
         <div class="nut-tab" :class="{'nut-tab-horizontal' : positionNavCss}">
-            <template v-if="positionNav=='top'">
-                <div class="nut-tab-title">
-                    <b class="nav-bar" :style="[{transform:'translateX('+initX+'px)'},{width:navWidth+'px'}]"></b>
-                    <span v-for="(value,index) in tabTitleList"  
+            <div v-if="positionNav=='right' || positionNav=='bottom'" class="nut-tab-item" ref="items">
+                <slot></slot>
+            </div>
+            <div :class="titleCLass">
+                <b v-if="isShowLine" :class="navBarClass" :style="navBarStyle"></b>
+                <span 
+                    v-for="(value,index) in tabTitleList"  
                     :key="index"
-                    @click="switchTab(index,$event,value.disable)" class="nut-title-nav-list" 
-                    :class="['nut-title-nav',{'nut-tab-disable':value.disable},{'nut-tab-active' : activeIndex == index}]"
-                    >
-                    <a :href="value.href" :clstag="value.clstag" class="nut-tab-link" v-on:click="switchTabLink(index,$event,value.disable)">
-                    <i class="nut-tab-icon" :style="{backgroundImage: 'url('+value.iconUrl+')'}" v-if="value.iconUrl"></i>
-                    {{value.tabTitle}}
+                    :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>
-                <div class="nut-tab-item">
-                    <slot></slot>
-                </div>  
-            </template>
-            <template v-else-if="positionNav=='left'">
-                <div class="nut-tab-title-leftnav">
-                    <b class="nav-bar-left" :style="[{transform:'translateY('+initX+'px)'},{height:navWidth+'px'}]"></b>
-                    <span v-for="(value,index) in tabTitleList" 
-                    :key="index"
-                    @click="switchTab(index,$event,value.disable)" class="nut-title-nav-leftnav" 
-                    :class="['nut-title-nav',{'nut-tab-disable':value.disable},{'nut-tab-active' : activeIndex == index}]"
-                    >
-                    <a :href="value.href" :clstag="value.clstag" class="nut-tab-link" v-on:click="switchTabLink(index,$event,value.disable)">
-                    <i class="nut-tab-icon" :style="{backgroundImage: 'url('+value.iconUrl+')'}" v-if="value.iconUrl"></i>
-                    {{value.tabTitle}}
-                    </a>
-                    </span>
-                </div>
-                <div class="nut-tab-item">
-                    <slot></slot>
-                </div>  
-            </template>
-            <template v-else-if="positionNav=='right'">
-                <div class="nut-tab-item">
-                    <slot></slot>
-                </div>
-                <div class="nut-tab-title-rightnav">
-                    <b class="nav-bar-right" :style="[{transform:'translateY('+initX+'px)'},{height:navWidth+'px'}]"></b>
-                    <span v-for="(value,index) in tabTitleList" 
-                    :key="index"
-                    @click="switchTab(index,$event,value.disable)" class="nut-title-nav-rightnav" 
-                    :class="['nut-title-nav',{'nut-tab-disable':value.disable},{'nut-tab-active' : activeIndex == index}]"
-                    >
-                    <a :href="value.href" :clstag="value.clstag" class="nut-tab-link" v-on:click="switchTabLink(index,$event,value.disable)">
-                    {{value.tabTitle}}
-                    <i class="nut-tab-icon" :style="{backgroundImage: 'url('+value.iconUrl+')'}" v-if="value.iconUrl"></i>
-                    </a>
-                    </span>
-                </div>
-            </template>
-            <template v-else-if="positionNav=='bottom'">
-                <div class="nut-tab-item">
-                    <slot></slot>
-                </div> 
-                    <div class="nut-tab-title-bottomnav">
-                    <b class="nav-bar-bottom" :style="[{transform:'translateX('+initX+'px)'},{width:navWidth+'px'}]"></b>
-                    <span v-for="(value,index) in tabTitleList" 
-                    :key="index"
-                    @click="switchTab(index,$event,value.disable)" class="nut-title-nav-list" 
-                    :class="['nut-title-nav',{'nut-tab-disable':value.disable},{'nut-tab-active' : activeIndex == index}]"
-                    >
-                    <a :href="value.href" :clstag="value.clstag" class="nut-tab-link" v-on:click="switchTabLink(index,$event,value.disable)">
-                    <i class="nut-tab-icon" :style="{backgroundImage: 'url('+value.iconUrl+')'}" v-if="value.iconUrl"></i>
-                    {{value.tabTitle}}
-                    </a>
-                    </span>
-                </div>
-            </template>
+                </span>
+            </div>
+            <div v-if="positionNav=='top' || positionNav=='left'" class="nut-tab-item" ref="items">
+                <slot></slot>
+            </div>  
         </div>
     </div>
 </template>
@@ -80,13 +27,17 @@
 export default {
     name:'nut-tab',
     props: {
+        'isShowLine':{
+            type:Boolean,
+            default:true
+        },
         'defIndex':{
             type:Number,
-            default:0,
+            default:0
         },
         'positionNav':{
             type:String,
-            default:'top',
+            default:'top'
         },
         'initData':{
             type:Array,
@@ -99,8 +50,7 @@ export default {
         return {
             tabTitleList:[],
             activeIndex:this.defIndex,
-            showTabs:true,
-            initX:'0px',
+            initX:'0',
             navWidth:0,
         };
     },
@@ -116,9 +66,41 @@ 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'){
+                return "nut-title-nav-list"
+            }
+            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'
+                }
+            }else{
+                return  {
+                    "transform": `translateY(${this.initX}px)`,
+                    "height": this.navWidth+'px'
+                }
+            }
+        }
     },
     mounted() {
         this.$nextTick(()=>{
@@ -126,12 +108,12 @@ export default {
         })     
     },
     methods: {
-        updeteTab:function(){
-            setTimeout(()=>{;
+        updeteTab:function(){  
+            this.$nextTick(()=>{;
                 this.tabTitleList = [];
                 this.activeIndex = this.defIndex;
                 this.initTab([...this.$slots.default]);  
-            },100);  
+            });
         },
         initTab:function(slot){
             for(let i = 0; i < slot.length; i++) {
@@ -146,16 +128,16 @@ export default {
                     this.tabTitleList.push(item);
                     let slotElm = slot[i].elm;
                     if(slotElm){
-                        this.addClass(slotElm,'hide');
+                        slotElm.classList.add('hide');
                         if(this.activeIndex == i) {
-                            this.removeClass(slotElm,'hide');
+                            slotElm.classList.remove('hide');
                         }
                     }                
                 }
             }
-            setTimeout(()=>{
+            this.$nextTick(()=>{
                 this.getTabWidth();
-            },0);
+            })
         },
         getStyle:function(obj,styleName){
             if(!obj){
@@ -184,41 +166,35 @@ export default {
             this.navWidth = navBarWidth;
             this.initX= parseInt(this.navWidth * this.defIndex);
         },
-        hasClass:function( elements,cName ){ 
-            return !!elements.className.match( new RegExp( "(\\s|^)" + cName + "(\\s|$)") ); // ( \\s|^ ) 判断前面是否有空格 (\\s | $ )判断后面是否有空格 两个感叹号为转换为布尔值 以方便做判断 
-        },
-        addClass:function( elements,cName ){ 
-            if(!this.hasClass( elements,cName ) ){ 
-                elements.className += " " + cName; 
-            }; 
-        },
-        removeClass:function ( elements,cName ){ 
-            if( this.hasClass( elements,cName ) ){ 
-                elements.className = elements.className.replace( new RegExp( "(\\s|^)" + cName + "(\\s|$)" )," " ); // replace方法是替换 
-            }; 
-        }, 
-        switchTabLink:function(index,event,disable){
-            if(!disable){
-                event.target.parentNode.click();
-            } 
+        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 && event.target.className.indexOf('nut-title-nav')!==-1){
+            if(!disable){
                 this.activeIndex=index;
                 this.initX= parseInt(this.navWidth * index);
-                let nutTab = event.target.parentNode.parentNode;
-                let items =  this.positionNav=='bottom' || this.positionNav=='right' ? nutTab.children[0].children : nutTab.children[1].children;
+                let nutTab = this.findParent(event,'nut-tab-part');
+                let items = this.$refs.items.children;
                 for(let i=0;i<items.length;i++){
                     if(i==index){
-                        this.removeClass(items[i],'hide');
+                        items[i].classList.remove('hide');
                     }else{
-                        this.addClass(items[i],'hide');
+                        items[i].classList.add('hide');
                     }
                 }
                 this.$emit('tab-switch',index,event); 
                 this.$emit('tabSwitch',index,event); //兼容以前驼峰法命名
             }
         }
-    },
+    }
 }
 </script>

+ 15 - 15
src/packages/tabbar/demo.vue

@@ -18,20 +18,20 @@ export default {
         {
           'tabTitle':'日用品',
           'curr':true,
-          'icon':'http://img13.360buyimg.com/uba/jfs/t30331/209/562746340/2190/6619973d/5bf763aaN6ff02099.jpg',
-          'activeIcon':'http://img20.360buyimg.com/uba/jfs/t28675/125/569589124/2710/fe1b0e7c/5bf79218Nbc49fc24.jpg'
+          'icon':'https://img14.360buyimg.com/imagetools/jfs/t1/127072/2/1076/4692/5eb93ab4Ec8c415b7/b8c5dda3f2d0f6a6.png',
+          'activeIcon':'https://img14.360buyimg.com/imagetools/jfs/t1/127314/1/1110/6272/5eb93ab9E9b708938/6ea8b9d6d13ca396.png'
         },
         {
           'tabTitle':'服饰',
           'curr':false,
-          'icon':'http://img13.360buyimg.com/uba/jfs/t27280/289/2061314663/2392/872e32ff/5bf76318Ndc80c1d8.jpg',
-          'activeIcon':'http://img14.360buyimg.com/uba/jfs/t28468/128/565494642/3313/ce508dd6/5bf79214Nab2a3076.jpg'
+          'icon':'https://img10.360buyimg.com/imagetools/jfs/t1/122494/19/1075/6299/5eb93b05E3674bd7e/7f10f0774b6ca63a.png',
+          'activeIcon':'https://img14.360buyimg.com/imagetools/jfs/t1/119999/25/1142/8218/5eb93b09E1a8c228f/907bcc2818e590c7.png'
         },
         {
           'tabTitle':'娱乐',
           'curr':false,
-          'icon':'http://img10.360buyimg.com/uba/jfs/t26779/215/2118525153/2413/470d1613/5bf767b2N075957b7.jpg',
-          'activeIcon':'http://img11.360buyimg.com/uba/jfs/t27370/260/2117900302/3274/bd097e85/5bf7921bNafc526e2.jpg'
+          'icon':'https://img12.360buyimg.com/imagetools/jfs/t1/113878/31/6319/6100/5eb93b6cEdb187192/68176aa418a2f511.png',
+          'activeIcon':'https://img11.360buyimg.com/imagetools/jfs/t1/127726/7/1065/8167/5eb93b70Eae11b392/cba15d13b435872b.png'
         }
       ],
       tabList2:[
@@ -39,7 +39,7 @@ export default {
           'tabTitle':'百度',
           'curr':false,
           'icon':'',
-          'num':5,
+          'num':13,
         },
         {
           'tabTitle':'京东',
@@ -56,30 +56,30 @@ export default {
         {
           'tabTitle':'主页',
           'curr':true,
-          'icon':'http://img13.360buyimg.com/uba/jfs/t1/29316/38/1115/3203/5c0f3d61E35d0c7da/9e557f2cb5c9dab6.jpg',
-          'activeIcon':'http://img20.360buyimg.com/uba/jfs/t1/9996/36/8646/4833/5c0f3d61E7c1b7e0f/c98ad61124172e93.jpg',
+          'icon':'https://img14.360buyimg.com/imagetools/jfs/t1/115926/10/6303/6603/5eb93bdeE8951c288/d277b2a668645e73.png',
+          'activeIcon':'https://img12.360buyimg.com/imagetools/jfs/t1/126024/30/1055/6952/5eb93be3E45d921c4/3060f25d49fc4ae7.png',
           'href':'###'
         },
         {
           'tabTitle':'分类',
           'curr':false,
-          'icon':'http://img12.360buyimg.com/uba/jfs/t1/25443/23/1062/4600/5c0f3d61E2e9f1360/c9b3421fe18614e2.jpg',
-          'activeIcon':'http://img20.360buyimg.com/uba/jfs/t1/19241/12/1048/8309/5c0f3d61E17ed5a56/c3af0964cade47f8.jpg',
+          'icon':'https://img12.360buyimg.com/imagetools/jfs/t1/113925/39/6348/5096/5eb94318E4037bdfc/1909ae8058e42cf5.png',
+          'activeIcon':'https://img10.360buyimg.com/imagetools/jfs/t1/118911/20/6244/5340/5eb9431cE8cd86a1d/1579cdf6ac2d1b8d.png',
           'href':'###'
         },
         {
           'tabTitle':'发现',
           'curr':false,
-          'icon':'http://img13.360buyimg.com/uba/jfs/t1/10361/35/4713/4643/5c0f3d62E437a3c94/273fd0fb90798f03.jpg',
-          'activeIcon':'http://img14.360buyimg.com/uba/jfs/t1/26604/35/1073/7896/5c0f3d61Eb9f5f184/5f01c938abe4216d.jpg',
+          'icon':'https://img14.360buyimg.com/imagetools/jfs/t1/127703/8/1017/7162/5eb93ea5Ed45cba37/fb52534fc21cc790.png',
+          'activeIcon':'https://img12.360buyimg.com/imagetools/jfs/t1/119259/20/6245/9589/5eb93ea9E1377964b/0c97f713361320b1.png',
           'href':'###'
         },
         {
           'tabTitle':'购物车',
           'curr':false,
           'num':2,
-          'icon':'http://img11.360buyimg.com/uba/jfs/t1/14848/18/1066/3723/5c0f41bdE9f2a38fe/e6ed6768717297fb.jpg',
-          'activeIcon':'http://img30.360buyimg.com/uba/jfs/t1/17538/16/1070/6214/5c0f41bdE4bc9a1db/74cf978e5015454b.jpg',
+          'icon':'https://img11.360buyimg.com/imagetools/jfs/t1/126465/3/1055/5848/5eb93f31E0ce4f65b/087c08eaeef97b64.png',
+          'activeIcon':'https://img10.360buyimg.com/imagetools/jfs/t1/111251/23/6376/6446/5eb93f2dE659da502/41fea546d36b8aaa.png',
           'href':'###'
         },
         {

+ 9 - 2
src/packages/tabbar/doc.md

@@ -61,7 +61,7 @@ export default {
           'tabTitle':'百度',
           'curr':false,
           'icon':'',
-          'num':5,
+          'num':13,
         },
         {
           'tabTitle':'京东',
@@ -157,13 +157,20 @@ export default {
 
 | 字段 | 说明 | 类型 | 默认值
 |----- | ----- | ----- | ----- 
-| type | 页签栏的样式 based/card | String | based
+| type | 页签栏的样式 based/card:based是默认样式如吸底样式,card类型每个卡片间有边界线 | String | based
 | tabbar-list | 渲染数据 ,兼容 tabbar-list 和 tabbarList| Array | []
+| bottom | 是否固定在页面底部 |Booble|false|
+
+### tabbar-list
+
+| 字段 | 说明 | 类型 | 默认值
+|----- | ----- | ----- | ----- 
 | tabTitle | 标签页的标题 | String | --
 | curr | 是否为选中的标签页 | Booble | false
 | icon | 标签页显示的图片 | String | --
 | activeIcon | 标签页的活动状态显示的图片 | String | --
 | href | 标签页的跳转链接 | String | --
+| num |页签右上角的数字角标,超出99之后为省略号|Number|--
 
 
 ### Event

+ 9 - 9
src/packages/tabbar/tabbar.scss

@@ -40,21 +40,21 @@
 	position: relative;
 	.tips{
 		position: absolute;
-		min-width: 14px;
-		min-height: 14px;
-		display: flex;
-		justify-content:center;
-		align-items: center;
-		padding:0;
+		width: 20px;
+		height: 20px;
+		text-align: center;
 		border:1px solid $border-color-active;
 		border-radius: 50%;
 		top: -10px;
-		right: 0;
-		background:#fff;
+		right: -5px;
+		background:red;
 		box-shadow: 0 0 0 1px #fff;
 		transform: translateX(60%);
 		font-size: $font-size-small;
-		color: $primary-color;
+		color: #fff;
+	}
+	.num{
+		line-height: 20px;
 	}
 }
 .icon-box .icon{

+ 9 - 16
src/packages/tabbar/tabbar.vue

@@ -2,16 +2,16 @@
     <div class="nut-tabbar" :class="{'bottom':bottom}">
         <a class="tabbar-nav" 
         v-for="(value,index) in tabList" 
-        :class="[{'curr':value.curr},type]"
+        :class="[{'curr':index == currIndex},type]"
         :key="value.tabTitle"
         v-on:click="switchTabs(value,index)"
         :href="value.href"
         >   
         <span class="icon-box">
-            <b class="tips" v-if="value.num">{{value.num}}</b>
+            <b class="tips num" v-if="value.num&&value.num<=99">{{value.num}}</b>
+            <b class="tips" v-else-if="value.num&&value.num>100">{{'...'}}</b>
             <template v-if="value.icon">
-                <div class="icon" v-if="value.curr" :style="{backgroundImage: 'url('+value.activeIcon+')'}"></div>
-                <div class="icon" v-else :style="{backgroundImage: 'url('+value.icon+')'}"></div>
+                <div class="icon" :style="{backgroundImage: `url(${index == currIndex ?value.activeIcon:value.icon})`}"></div>
             </template>
             <span :class="['tabbar-nav-word',{'big-word':!value.icon}]">{{value.tabTitle}}</span>
         </span>
@@ -26,19 +26,20 @@ export default {
             type:Array,
             default:()=>{
                 return [];
-            },
+            }
         },
         'bottom':{
             type:Boolean,
-            default:false,
+            default:false
         },
         'type':{
             type:String,
-            default:'based',
+            default:'based'
         }
     },
     data() {
         return {
+          currIndex:null,
           tabList:this.tabbarList
         };
     },
@@ -52,15 +53,7 @@ export default {
     },
     methods: {
         switchTabs:function(value,index){
-            let newArr = this.tabList.map((item,idx)=>{
-                if(index == idx){
-                   item.curr = true;
-                }else{
-                   item.curr = false;
-                }
-                return item;
-            })
-            this.tabList =newArr;
+            this.currIndex = index;
             this.$emit('tab-switch',value,index); 
             this.$emit('tabSwitch',value,index); //兼容以前驼峰法
         }