Browse Source

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

yewenwen3 5 years ago
parent
commit
6b65f04c70

+ 1 - 1
.travis.yml

@@ -1,7 +1,7 @@
 sudo: required
 language: node_js
 node_js:
-  - '8'
+  - '10'
 script:
   - npm test
   - npm run coveralls

+ 18 - 0
CHANGELOG.md

@@ -1,3 +1,21 @@
+## 2.2.5
+
+`2020-05-25`
+
+* :sparkles: feat(Address):新增地址组件 @yangxiaolu1993
+* :sparkles: upd(Popup):优化内部代码、单元测试 @yangkaixuan
+* :sparkles: upd(LeftSlip):重构优化代码 #229 @vickyYE
+* :sparkles: upd(Video):修复自定义蒙层 @vickyYE
+* :sparkles: upd(Tab):优化内部代码,支持多页签滑动 @zhenyulei
+* :bug: fix(Range):stage 失效、控制器重叠问题 #242 @undo03
+* :bug: fix(CountDown):修复 startTime 异步更新问题 @undo03
+* :bug: fix(Icon):修复 url 异步更新问题 @richard1015
+* :bug: fix(Swiper):修复 cdn 模式下 event 事件失效问题 @richard1015
+* :bug: fix(Dialog):修复标签使用时,取消按钮无效 @guoxiao158
+* :zap: doc:nutui-demo、user-case jdf2e 地址库更换 @richard1015
+* :zap: doc:补充 rate js 文档 @richard1015
+* :zap: doc:补充 switch demo 文档 @zjyau
+
 ## 2.2.4
 
 `2020-04-29`

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
     "name": "@nutui/nutui",
-    "version": "2.2.4",
+    "version": "2.2.5",
     "description": "一套轻量级移动端Vue组件库",
     "typings": "dist/types/index.d.ts",
     "main": "dist/nutui.js",

+ 3 - 3
src/nutui.js

@@ -120,8 +120,8 @@ import SideNavBarItem from "./packages/sidenavbaritem/index.js";
 import "./packages/sidenavbaritem/sidenavbaritem.scss";
 import Drag from "./packages/drag/index.js";
 import "./packages/drag/drag.scss";
-import VueQr from "./packages/qart/index.js";
-import "./packages/qart/qart.scss";
+// import VueQr from "./packages/qart/index.js";
+// import "./packages/qart/qart.scss";
 import Address from "./packages/address/index.js";
 import "./packages/address/address.scss";
 
@@ -264,7 +264,7 @@ export default {
   locale,
   install,
   Lazyload,
-  VueQr,
+  // VueQr,
 
   ...components,
   ...filters,

+ 1 - 1
src/packages/elevator/elevator.scss

@@ -1,5 +1,5 @@
 .nut-elevator{
-    position: fixed;
+    position:relative;
     top:40px;
     width: 100%;
 }

+ 24 - 0
src/packages/rate/doc.md

@@ -48,6 +48,30 @@
 ></nut-rate>
 ```
 
+```javascript
+export default {
+    data(){
+        return{
+            val:4,
+            val2:2,
+            result:'',
+            result2:'',
+            icon1:`url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='rgb(255,0,0)' d='M10 20a10 10 0 1 1 0-20 10 10 0 0 1 0 20zM6.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm7 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm2.16 3H4.34a6 6 0 0 0 11.32 0z'/%3E%3C/svg%3E")`,
+            icon2:`url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='rgb(255,0,0)' d='M10 20a10 10 0 1 1 0-20 10 10 0 0 1 0 20zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM6.5 9a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm7 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM7 13h6a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2z'/%3E%3C/svg%3E")`
+        }
+    },
+   
+    methods:{
+        onClick(idx){
+            this.result = '您点击了第'+idx+'个!';
+        },
+        onClick2(idx){
+            this.result2 = '您点击了第'+idx+'个!';
+        }
+    }
+}
+```
+
 ## Prop
 
 | 字段 | 说明 | 类型 | 默认值

+ 0 - 1
src/packages/switch/__test__/switch.spec.js

@@ -83,5 +83,4 @@ describe('Switch.vue', () => {
             }, 350);
         });
     });
-
 });

+ 16 - 1
src/packages/switch/demo.vue

@@ -43,6 +43,13 @@
         </div>
         <p>禁用状态下,change事件参数永远为初始值</p>
 
+        <h4>循环场景</h4>
+        <div v-for="(item, index) of list" :key="index">
+            <nut-cell>
+                <span slot="title"> {{ item.name }}</span>
+                <span slot="desc"><nut-switch @change="onChangeLabel($event,index)" :active="true"></nut-switch></span>
+            </nut-cell>
+        </div>
         <h4>自定义Class</h4>
         <div>
             <nut-cell>
@@ -56,12 +63,20 @@
 export default {
   data() {
     return {
-      swActive: true
+      swActive: true,
+      list:[
+        {id:'1',name:'a'},
+        {id:'2',name:'b'},
+        {id:'3',name:'c'}
+        ]
     };
   },
   methods: {
     onChange(status) {
       alert(status);
+    },
+    onChangeLabel(status,index){
+      alert('status:'+status+',selected:'+index);
     }
   }
 };

+ 5 - 5
src/packages/switch/doc.md

@@ -49,15 +49,15 @@ export default {
 ## change事件
 ```html
 <nut-switch 
-  @change="onChange"
+  @change="onChange($event,'1')"
 >
 </nut-switch>
 ```
 ```javascript
 export default {
   methods: {
-    onChange(status) {
-      alert(status);
+    onChange(status,index) {
+      alert('status:'+status+',selected:'+index);
     }
   }
 };
@@ -85,7 +85,7 @@ export default {
 ## Prop
 
 | 字段 | 说明 | 类型 | 默认值
-|----- | ----- | ----- | ----- 
+|----- | ----- | ----- | -----
 | active | 开关状态 | Boolean | false
 | size | 尺寸,可选值small/base/large | String | base
-| disabled | 是否禁用 | Boolean | false
+| disabled | 是否禁用 | Boolean | false

+ 2 - 5
src/packages/switch/switch.vue

@@ -26,8 +26,7 @@ export default {
   },
   data() {
     return {
-      isActive: false,
-      isAnimating:false
+      isActive: false
     };
   },
   created() {
@@ -40,16 +39,14 @@ export default {
   },
   methods: {
     toggle() {
-      if(this.isAnimating) return;
       const status = this.isActive;
       if (!this.disabled) {
         this.isActive = !status;
       }
-      this.isAnimating = true;
+
       setTimeout(() => {
         this.$emit("change", this.isActive);
         this.$emit("update:active", this.isActive);
-        this.isAnimating = false;
       }, 300);
     }
   }

+ 28 - 1
src/packages/tab/demo.vue

@@ -6,7 +6,9 @@
         <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>
+
     <h4>支持导航条在上下左右位置</h4>
     <nut-tab @tab-switch="tabSwitch">
       <nut-tab-panel
@@ -35,6 +37,7 @@
         v-html="value.content"
       ></nut-tab-panel>
     </nut-tab>
+    
     <nut-tab @tab-switch="tabSwitch" position-nav="bottom">
       <nut-tab-panel
         v-for="value in editableTabs"
@@ -45,10 +48,32 @@
       ></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>
+    </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">
+    <nut-tab :def-index="defIndex" class="customer-css" @tab-switch="tabSwitch" :contentShow="true" :init-data="disableTabs" :is-show-line="false">
       <nut-tab-panel
         v-for="value in disableTabs"
         v-bind:key="value.tabTitle"
@@ -210,6 +235,8 @@ export default {
   .nut-tab-active {
     background: $primary-color;
     border: 0;
+    transition: all 0.3s ease-in-out;
+
   }
   .nav-bar {
     background: $primary-color;

+ 27 - 2
src/packages/tab/doc.md

@@ -75,6 +75,31 @@ export default {
   }
 };
 ```
+## 支持滑动选择多个页签
+
+```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>
+```
+
+```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>
+```
 
 ## 禁止选中,默认选中某个标签,如需更新数组后,重新渲染Tab页面,请将更新数组传入init-data
 
@@ -202,8 +227,8 @@ export default {
 | position-nav | 页签栏的分布,可选值 top/bottom/left/right | String | top
 | def-index | 默认选中的页签栏 | String | 1
 | init-data | 监听数据变化,渲染更新页面 | Array | []
-| is-show-line|是否显示tab切换时的红条|true|
-
+| is-show-line|是否显示tab切换时的红条|Boolean|true|
+| is-scroll|是否支持滑动选择多个页签|Boolean|false|
 
 ### nut-tab-panel
 

+ 150 - 94
src/packages/tab/tab.scss

@@ -1,17 +1,17 @@
-.nut-tab{
+.nut-tab {
     position: relative;
-    border:1px solid #eee;
+    border: 1px solid #eee;
     padding: 10px;
     font-size: 12px;
-    background:#eee;
-}
-.nut-tab-horizontal{
+    background: #eee;
+  }
+  .nut-tab-horizontal {
     display: flex;
     flex-direction: row;
     position: relative;
-}
-
-.close-btn{
+  }
+  
+  .close-btn {
     position: absolute;
     width: 17px;
     height: 17px;
@@ -24,8 +24,8 @@
     right: 0px;
     top: 0px;
     border-radius: 50%;
-}
-.nut-tab-horizontal .close-btn{
+  }
+  .nut-tab-horizontal .close-btn {
     position: absolute;
     width: 17px;
     height: 17px;
@@ -38,145 +38,201 @@
     right: 0px;
     top: 0px;
     border-radius: 50%;
-}
-.nut-tab-title{
+  }
+  .nut-tab-title {
     //border:1px solid #fff;
-    border-bottom:1px solid #EDEDED;
+    border-bottom: 1px solid #ededed;
     width: 100%;
     display: flex;
     height: 50px;
     line-height: 48px;
     box-sizing: border-box;
-    position: relative;   
-}
-.nav-bar{
+    position: relative;
+    overflow-x: auto;
+    overflow-y: hidden;
+    &::-webkit-scrollbar {
+        display: none;
+    }
+  }
+  .nav-bar {
     position: absolute;
     height: 2px;
-    bottom: -2px;
+    bottom: 0px;
     left: 0px;
-    background:$primary-color;
-    transition: all 0.4s ease-in-out;
-}
-.nut-tab-title-leftnav{
-    border-right:1px solid #EDEDED;
+    z-index: 2;
+    background: $primary-color;
+    transition: all 0.3s ease-in-out;
+  }
+  .nut-tab-title-leftnav {
+    border-right: 1px solid #ededed;
     width: 100px;
     display: flex;
     background: #fff;
-    flex-direction: column; 
+    flex-direction: column;
     position: relative;
-    .nav-bar-left{
-        position: absolute;
-        width: 2px;
-        right: -2px;
-        top: 0px;
-        background:$primary-color;
-        transition: all 0.4s ease-in-out;
+    height: 200px;
+    overflow-y: auto;
+    overflow-x: hidden;
+    &::-webkit-scrollbar {
+        display: none;
+    }
+    .nav-bar-left {
+      position: absolute;
+      width: 2px;
+      right: 0px;
+      top: 0px;
+      z-index: 2;
+      background: $primary-color;
+      transition: all 0.3s ease-in-out;
     }
-    .nut-title-nav{
-        border:0;
-        border-left:1px solid #F5F7FA;
+    .nut-title-nav {
+      border: 0;
+      border-left: 1px solid #f5f7fa;
     }
-    .nut-tab-active{
-        background: #fff;
+    .nut-tab-active {
+      background: #fff;
+    //   a{
+    //     color: red;
+    //   }
     }
-}
-.nut-tab-title-rightnav{
+  }
+  .nut-tab-title-rightnav {
     background: #fff;
-    border:1px solid #fff;
-    border-left:1px solid #EDEDED;
+    // border: 1px solid #fff;
+    border-left: 1px solid #ededed;
     width: 100px;
     display: flex;
-    flex-direction: column; 
+    flex-direction: column;
     position: relative;
-    .nav-bar-right{
-        position: absolute;
-        width: 2px;
-        left: -2px;
-        top: 0px;
-        background:$primary-color;
-        transition: all 0.4s ease-in-out;
+    overflow-y: auto;
+    overflow-x: hidden;
+    height: 200px;
+    box-sizing: border-box;
+    &::-webkit-scrollbar {
+        display: none;
+    }
+    .nav-bar-right {
+      position: absolute;
+      width: 2px;
+      left: 0px;
+      top: 0px;
+      z-index:2;
+      background: $primary-color;
+      transition: all 0.3s ease-in-out;
     }
-}
-.nut-tab-link{
+  }
+  .nut-tab-link {
     color: #333;
     display: flex;
-    align-items:center;
-    justify-content:center;
-    font-size:12px;
-    text-decoration:none;
+    align-items: center;
+    justify-content: center;
+    font-size: 12px;
+    text-decoration: none;
     line-height: 1;
-}
-.nut-tab-title-bottomnav{
-    border:1px solid #fff;
-    border-top:1px solid #EDEDED;
+    width: 100%;
+    height:100%;
+  }
+  .nut-tab-title-bottomnav {
+    border: 1px solid #fff;
+    border-top: 1px solid #ededed;
     width: 100%;
     display: flex;
     height: 50px;
-    line-height: 49px; 
+    line-height: 49px;
     box-sizing: border-box;
     position: relative;
-    .nav-bar-bottom{
-        position: absolute;
-        height: 2px;
-        left: 0px;
-        top: -2px;
-        background:$primary-color;
-        transition: all 0.4s ease-in-out;
+    overflow-x: auto;
+    overflow-y: hidden;
+    &::-webkit-scrollbar {
+        display: none;
     }
-}
-
-.nut-title-nav-list{
+    .nav-bar-bottom {
+      position: absolute;
+      height: 2px;
+      left: 0px;
+      top: 0px;
+      z-index: 2;
+      background: $primary-color;
+      transition: all 0.3s ease-in-out;
+    }
+  }
+  
+  .nut-title-nav-list {
     flex: 1;
     position: relative;
     flex-direction: row;
-    align-items:center;
-    justify-content:center;
+    align-items: center;
+    justify-content: center;
     display: flex;
     background: #fff;
     box-sizing: border-box;
-}
-.nut-title-nav-leftnav{
-    flex:1;
+  }
+  .nut-title-nav-leftnav {
+    flex: 1;
     display: flex;
     padding-left: 5px;
     //justify-content: center;
     align-items: center;
     position: relative;
-}
-.nut-title-nav-rightnav{
-    flex:1;
+  }
+  .nut-title-nav-rightnav {
+    flex: 1;
     display: flex;
     padding-right: 5px;
     justify-content: flex-end;
     align-items: center;
     position: relative;
-}
-.nut-tab-icon{
+  }
+  .nut-title-nav-scroll{
+    min-width: 100px;
+    position: relative;
+    flex-direction: row;
+    align-items: center;
+    justify-content: center;
+    display: flex;
+    background: #fff;
+    box-sizing: border-box;
+  }
+  .nut-title-vertical-scroll{
+    min-height: 55px;
+    position: relative;
+    flex-direction: row;
+    align-items: center;
+    justify-content: center;
+    display: flex;
+    background: #fff;
+    box-sizing: border-box;
+  }
+  .nut-tab-icon {
     display: inline-block;
     margin-right: 5px;
     width: 20px;
     height: 20px;
-    background-repeat: no-repeat; 
-    background-size:100% 100%;
-}
-.nut-tab-active{
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+  }
+  .nut-tab-active {
     background: #fff;
     border: 0;
-}
-.nut-tab-item {  
+    // a{
+    //     color: red;
+    // }
+  }
+  .nut-tab-item {
     height: 200px;
-    border:1px solid #fff;
-    background:#fff;
+    border: 1px solid #fff;
+    background: #fff;
     width: 100%;
     padding: 10px;
     box-sizing: border-box;
-    .hide{
-        display: none;
+    .hide {
+      display: none;
     }
-}
-.nut-tab-disable{
+  }
+  .nut-tab-disable {
     background: #e1e1e1 !important;
-}
-.tabbar-nav-word{
-    font-size:$font-size-small;
-}
+  }
+  .tabbar-nav-word {
+    font-size: $font-size-small;
+  }
+  

+ 183 - 184
src/packages/tab/tab.vue

@@ -1,200 +1,199 @@
 <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">
-                <slot></slot>
-            </div>
-            <div :class="titleCLass">
-                <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>
-            <div v-if="positionNav=='top' || positionNav=='left'" class="nut-tab-item" ref="items">
-                <slot></slot>
-            </div>  
-        </div>
+  <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">
+        <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>
+      <div v-if="positionNav == 'top' || positionNav == 'left'" class="nut-tab-item" ref="items">
+        <slot></slot>
+      </div>
     </div>
+  </div>
 </template>
 <script>
 export default {
-    name:'nut-tab',
-    props: {
-        'isShowLine':{
-            type:Boolean,
-            default:true
-        },
-        'defIndex':{
-            type:Number,
-            default:0
-        },
-        'positionNav':{
-            type:String,
-            default:'top'
-        },
-        'initData':{
-            type:Array,
-            default:function(){
-                return [];
-            }
-        }     
+  name: 'nut-tab',
+  props: {
+    isScroll:{
+        type:Boolean,
+        default:false
+    },
+    isShowLine: {
+      type: Boolean,
+      default: true
+    },
+    defIndex: {
+      type: Number,
+      default: 0
+    },
+    positionNav: {
+      type: String,
+      default: 'top'
+    },
+    initData: {
+      type: Array,
+      default: function() {
+        return [];
+      }
+    }
+  },
+  data() {
+    return {
+      tabTitleList: [],
+      activeIndex: this.defIndex,
+      initX: '0',
+      navWidth: 0
+    };
+  },
+  watch: {
+    defIndex() {
+      this.updeteTab();
+    },
+    initData: {
+      handler() {
+        this.updeteTab();
+      },
+      deep: true
+    }
+  },
+  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';
     },
-    data() {
+    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';
+      }
+      
+    },
+    navBarStyle: function() {
+    if (this.positionNav === 'top' || this.positionNav === 'bottom') {
         return {
-            tabTitleList:[],
-            activeIndex:this.defIndex,
-            initX:'0',
-            navWidth:0,
+          transform: `translateX(${this.initX}px)`,
+          width: this.navWidth + 'px'
         };
+    }
+    return {
+        transform: `translateY(${this.initX}px)`,
+        height: this.navWidth + 'px'
+    };
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.$slots.default && this.updeteTab(this.$slots.default);
+    });
+  },
+  methods: {
+    updeteTab: function() {
+      this.$nextTick(() => {
+        this.tabTitleList = [];
+        this.activeIndex = this.defIndex;
+        this.initTab([...this.$slots.default]);
+      });
     },
-    watch:{
-        defIndex(){
-            this.updeteTab();
-        },
-       initData:{
-           handler(){
-            this.updeteTab();
-           },
-           deep:true
-       }
-    },
-    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'
-                }
+    initTab: function(slot) {
+      for (let i = 0; i < slot.length; i++) {
+        let slotTag = slot[i].tag;
+        if (typeof slotTag == 'string' && slotTag.indexOf('nut-tab-panel') != -1) {
+          let attrs = slot[i].data.attrs;
+          let item = {
+            tabTitle: attrs['tab-title'] || attrs['tabTitle'],
+            disable: attrs.disable === false,
+            iconUrl: attrs['iconUrl'] || attrs['icon-url']
+          };
+          this.tabTitleList.push(item);
+          let slotElm = slot[i].elm;
+          if (slotElm) {
+              slotElm.classList.add('hide');
+            if (this.activeIndex == i) {
+              slotElm.classList.remove('hide');
             }
+          }
+        }
+      }
+      this.$nextTick(() => {
+        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.initX = parseInt(this.navWidth * this.defIndex);
+      });
     },
-    mounted() {
-        this.$nextTick(()=>{
-            this.$slots.default && this.updeteTab(this.$slots.default); 
-        })     
+    getStyle: function(obj, styleName) {
+      if (!obj) {
+        return '';
+      }
+      if (obj.currentStyle) {
+        return obj.currentStyle[styleName];
+      } else {
+        return getComputedStyle(obj, null)[styleName];
+      }
     },
-    methods: {
-        updeteTab:function(){  
-            this.$nextTick(()=>{;
-                this.tabTitleList = [];
-                this.activeIndex = this.defIndex;
-                this.initTab([...this.$slots.default]);  
-            });
-        },
-        initTab:function(slot){
-            for(let i = 0; i < slot.length; i++) {
-                let slotTag = slot[i].tag;
-                if(typeof(slotTag)=='string' && slotTag.indexOf('nut-tab-panel') != -1) {
-                    let attrs = slot[i].data.attrs;
-                    let item ={
-                        'tabTitle':attrs['tab-title'] || attrs['tabTitle'],
-                        'disable':attrs.disable===false,
-                        'iconUrl':attrs['iconUrl'] || attrs['icon-url'],
-                    }
-                    this.tabTitleList.push(item);
-                    let slotElm = slot[i].elm;
-                    if(slotElm){
-                        slotElm.classList.add('hide');
-                        if(this.activeIndex == i) {
-                            slotElm.classList.remove('hide');
-                        }
-                    }                
-                }
-            }
-            this.$nextTick(()=>{
-                this.getTabWidth();
-            })
-        },
-        getStyle:function(obj,styleName){
-            if(!obj){
-                return ''
-            }
-            if(obj.currentStyle){
-                return obj.currentStyle[styleName];
-            }else{
-                return getComputedStyle(obj,null)[styleName];
-            }
-        },
-        getTabWidth:function(){
-            if(this.positionNav=='top' || this.positionNav=='bottom'){
-                let tabTitle = document.querySelector('.nut-tab-title');
-                let tabWidth = this.getStyle(tabTitle,'width');
-                this.setInitX(tabWidth);
-            }else{
-                let tabTitle = document.querySelector('.nut-tab-title-leftnav')|| document.querySelector('.nut-tab-title-rightnav');
-                let tabWidth = this.getStyle(tabTitle,'height');
-                this.setInitX(tabWidth);
-            }
-        },
-        setInitX(tabWidth){
-            let tabWidthNum = tabWidth.substring(0,tabWidth.length-2);
-            let navBarWidth = (tabWidthNum/this.tabTitleList.length);
-            this.navWidth = navBarWidth;
-            this.initX= parseInt(this.navWidth * this.defIndex);
-        },
-        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');
-                let items = this.$refs.items.children;
-                for(let i=0;i<items.length;i++){
-                    if(i==index){
-                        items[i].classList.remove('hide');
-                    }else{
-                        items[i].classList.add('hide');
-                    }
-                }
-                this.$emit('tab-switch',index,event); 
-                this.$emit('tabSwitch',index,event); //兼容以前驼峰法命名
-            }
+    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');
+        let items = this.$refs.items.children;
+        for (let i = 0; i < items.length; i++) {
+          if (i == index) {
+            items[i].classList.remove('hide');
+          } else {
+            items[i].classList.add('hide');
+          }
         }
+        this.$emit('tab-switch', index, event);
+        this.$emit('tabSwitch', index, event); //兼容以前驼峰法命名
+      }
     }
-}
+  }
+};
 </script>

+ 9 - 7
src/packages/textbox/demo.vue

@@ -4,14 +4,14 @@
         <h4>默认用法 支持异步回显数据</h4>
          <nut-textbox v-model="val"></nut-textbox>
         <h4>自定义高度:100px</h4>
-        <nut-textbox :txtAreaH="100" :maxNum="300" :value="val"></nut-textbox>
+        <nut-textbox :txtAreaH="100" :maxNum="300" v-model="val"></nut-textbox>
 
         <h4>自定义提示语</h4>
-        <nut-textbox :placeText="'请填写详细情况请填写详细情况'"></nut-textbox>
+        <nut-textbox :placeText="'请填写详细情况请填写详细情况'" v-model="val1"></nut-textbox>
         
 
         <h4>自定义字数限制</h4>
-        <nut-textbox :maxNum="100"></nut-textbox>
+        <nut-textbox :maxNum="100" v-model="val2"></nut-textbox>
         
 
         <h4>限制字数不可超出</h4>
@@ -19,14 +19,14 @@
         
 
         <h4>字数超出报错</h4>
-        <nut-textbox :maxNum="10" :txtAreaH="100"  @errorFunc="overLength" ></nut-textbox>
+        <nut-textbox :maxNum="10" :txtAreaH="100"  @errorFunc="overLength" v-model="val1" ></nut-textbox>
         
 
         <h4>自定义文本框背景色</h4>
-        <nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="100" textBgColor="#feefef"></nut-textbox>
+        <nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="100" textBgColor="#feefef" v-model="val1"></nut-textbox>
 
         <h4>不显示字数限制</h4>
-        <nut-textbox :limitShow="false" :maxNum="10" ></nut-textbox>
+        <nut-textbox :limitShow="false" :maxNum="10" v-model="val1" ></nut-textbox>
        
         <h4>输入回调返回文字</h4>
         <nut-textbox  :maxNum="10" txtAreaH="100" @inputFunc="inputText" ></nut-textbox>
@@ -37,7 +37,9 @@
 export default {
     data(){
         return{
-            val: ''
+            val: '',
+            val1:"",
+            val2:"自定义数据"
         }
     },
     methods:{

+ 6 - 4
src/packages/textbox/doc.md

@@ -17,19 +17,19 @@
 ## 自定义提示语
 
 ```html
-<nut-textbox :placeText="'请填写详细情况请填写详细情况'"> </nut-textbox>
+<nut-textbox :placeText="'请填写详细情况请填写详细情况'" v-model="val1"> </nut-textbox>
 ```
 
 ## 自定义字数限制
 
 ```html
-<nut-textbox :maxNum="100"> </nut-textbox>
+<nut-textbox :maxNum="100" v-model="val2"> </nut-textbox>
 ```
 
 ## 限制字数不可超出
 
 ```html
-<nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="2" textBgColor="#efefef">
+<nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="2" textBgColor="#efefef" v-model="val2">
 </nut-textbox>
 ```
 
@@ -66,7 +66,9 @@
 export default {
   data() {
     return {
-      val: ''
+      val: '',
+      val1:'',
+      val2:'自定义数据'
     }
   },
   methods: {

+ 12 - 2
src/packages/textbox/textbox.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="nut-textbox">
         <div class="txt-area" :class="{'error':errorState,'num-none':limitShow == false}" :style="{background:textBgColor}">
-            <textarea :placeholder="placeText" :style="{height:txtAreaHeight+'px'}" v-model="value" @input="txtIptLength" :switchMax="switchMax" :maxlength="iptMaxlength"></textarea>
+            <textarea :placeholder="placeText" :style="{height:txtAreaHeight+'px'}"  v-model="currentValue" @input="txtIptLength" :switchMax="switchMax" :maxlength="iptMaxlength"></textarea>
             <span v-show="limitShow">{{txtNum}}/{{maxNum}}</span>
         </div>
     </div>
@@ -41,11 +41,22 @@ export default {
     },
     data() {
         return {
+           
             errorState:false,
             txtNum:0,
         };
     },
+    mounted(){
+       
+    },
     computed:{
+        currentValue:{
+            get(){
+                return this.value;
+            },
+            set(val){
+            }
+        },
         txtAreaHeight:function(){
            let txtAreaH;
            txtAreaH = this.txtAreaH;
@@ -63,7 +74,6 @@ export default {
     methods: {
         txtIptLength(event){
             const data = event.target.value
-            console.log(data)
             const txtLength = data.length;
             this.txtNum = txtLength;
             if(txtLength > this.maxNum) {

+ 3 - 2
src/packages/video/demo.vue

@@ -27,7 +27,7 @@
         </div>
         <h4>设置视频为背景图</h4>
         <p>当设置视频为背景图时需要将 muted 静音、 disabled 禁止操作、loop 循环播放、autoplay 自动播放设置为 true,移动端需要设置
-            playsinline 行内展示(兼容安卓用)</p>
+            playsinline 行内展示</p>
         <div class="video-con">
             <nut-video :sources="sources" :options="options6"></nut-video>
         </div>
@@ -89,7 +89,8 @@
                     muted: true,
                     disabled: true,
                     playsinline: true,
-                    loop: true
+                    loop: true,
+                    controls: false
                 },
 
             };

+ 17 - 0
src/packages/video/video.scss

@@ -66,6 +66,14 @@
         width: 100%;
         z-index: 11111111;
         align-items: center;
+        opacity: 0;
+        transition: all 1s;
+        &.show-control {
+            opacity: 1;
+        }
+        &.hide-control {
+            opacity: 0;
+        }
         .control-play-btn {
             width: 18px;
             height: 18px;
@@ -76,7 +84,16 @@
             background-repeat: no-repeat;
             background-position: center;
             margin: 0 10px;
+            &.puase {
+                background-image: -webkit-image-set(
+                    url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmZmZmIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik02IDE5aDRWNUg2djE0em04LTE0djE0aDRWNWgtNHoiLz4KICAgIDxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4KPC9zdmc+Cg==)
+                        1x
+                );
+                background-repeat: no-repeat;
+                background-position: center;
+            }
         }
+
         .duration-time,
         .current-time {
             color: #fff;

+ 44 - 36
src/packages/video/video.vue

@@ -7,7 +7,8 @@
         <div class="playing-mask" ref="touchMask" v-if="showToolbox && !isDisabled" @click="play"></div>
         <div class="nut-video-play-btn" v-if="showToolbox && !isDisabled" ref="palyBtn" v-show="!state.playing"
             @click="play"></div>
-        <div class="nut-video-controller" v-show="showToolbox && !isDisabled">
+        <div class="nut-video-controller" v-show="showToolbox && !isDisabled"
+            :class="{'show-control': !state.playing,'hide-control':state.playing}">
             <div class="control-play-btn" @click="play"></div>
             <div class="current-time">{{ videoSet.displayTime }}</div>
             <div class="progress-container">
@@ -22,7 +23,7 @@
                 </div>
             </div>
             <div class="duration-time">{{ videoSet.totalTime }}</div>
-            <div class="volume" @click="handleMuted"></div>
+            <div class="volume" @click="handleMuted" :class="{'muted':state.isMuted}"></div>
             <div class="fullscreen-icon" @click="fullScreen"></div>
         </div>
         <!-- 错误弹窗 -->
@@ -37,12 +38,12 @@
     export default {
         name: 'nut-video',
         props: {
-            src: '',
-            playsinline: {
-                type: Boolean,
-                default: false
+            sources: {
+                type: Array,
+                default() {
+                    return []
+                }
             },
-            sources: Array,
             options: {
                 type: Object,
                 default() {
@@ -60,6 +61,10 @@
                 },
                 required: true
             },
+            model: {
+                type: String,
+                default: ''
+            }
         },
         data() {
             return {
@@ -87,22 +92,23 @@
                     }
                 },
                 state: {
-                    contrlShow: false,
+                    controlShow: true,
                     vol: 0.5, //音量
                     currentTime: 0, //当前时间
                     fullScreen: false,
                     playing: false, //是否正在播放
                     isLoading: false,
                     isEnd: false,
-                    isError: false
+                    isError: false,
+                    isMuted: false
                 },
-                showTouchMask: false
+                showTouchMask: false,
             };
         },
         computed: {
             isDisabled() {
                 return this.options.disabled
-            },
+            }
 
         },
         watch: {
@@ -118,10 +124,25 @@
             },
             options: {
                 handler(val) {
-
+                    this.state.isMuted = val.muted ? val.muted : false
                 },
                 immediate: true
-            }
+            },
+            // model: {
+            //     handler(val) {
+            //         if (val) {
+            //             if (val == 'custom') {
+            //                 this.state.controlShow = false;
+            //                 this.showToolbox = this.options.controls ? true : false
+            //             }
+            //         } else {
+            //             this.showToolbox = false;
+            //             this.state.controlShow = this.options.controls ? true : false
+            //         }
+            //     },
+            //     immediate: true
+
+            // }
         },
         mounted() {
             this.init();
@@ -172,31 +193,22 @@
                 this.player.pos = $player.getBoundingClientRect();
                 this.progressBar.pos = $progress.getBoundingClientRect();
                 this.videoSet.progress.width = Math.round($progress.getBoundingClientRect().width);
-                console.log(this.progressBar.pos)
             },
             play() {
-                this.state.playing = !this.state.playing;
+
 
                 if (this.options.autoplay && this.options.disabled) {
                     this.state.playing = true;
+                    // this.state.controlShow = false
                     return false;
                 }
+                this.state.playing = !this.state.playing;
                 if (this.videoElm) {
 
-                    // if (this.state.playing) {
-                    //     this.videoElm.play();
-                    //     this.videoElm.addEventListener('ended', this.playEnded);
-                    //     this.$emit('play', this.video);
-                    // } else {
-                    //     this.videoElm.pause();
-                    //     this.$emit('pause', this.video);
-                    // }
                     // 播放状态
                     if (this.state.playing) {
                         try {
-                            // console.log(111)
                             this.videoElm.play();
-                            // this.isPauseTouch = false;
                             // 监听缓存进度
                             this.videoElm.addEventListener('progress', e => {
                                 this.getLoadTime();
@@ -213,23 +225,22 @@
                     }
                     // 停止状态
                     else {
-                        // console.log('pu')
-                        this.isPauseTouch = true;
                         this.videoElm.pause();
                         this.$emit('pause', this.videoElm);
+
                     }
                 }
             },
             // 音量控制
             volumeHandle() {
-                this.state.vol = this.videoElm.volume;
+                this.state.vol = this.options.volume;
             },
             // 静音控制
             handleMuted() {
-
+                this.state.isMuted = !this.state.isMuted
+                this.videoElm.muted = this.state.isMuted
             },
             playEnded() {
-                // console.log('ended')
                 this.state.playing = false;
                 this.state.isEnd = true;
                 this.state.controlBtnShow = true;
@@ -247,7 +258,7 @@
             fullScreen() {
                 if (!this.state.fullScreen) {
                     this.state.fullScreen = true;
-                    this.video.webkitRequestFullScreen();
+                    this.videoElm.webkitRequestFullScreen();
                 } else {
                     this.state.fullScreen = false;
                     document.webkitCancelFullScreen();
@@ -262,7 +273,6 @@
                 // 赋值时长
                 this.videoSet.totalTime = this.timeFormat(this.videoElm.duration);
                 this.videoSet.displayTime = this.timeFormat(this.videoElm.currentTime);
-                // console.log(this.videoSet, this.timeFormat(this.videoElm.duration), this.timeFormat(this.videoElm.currentTime), this.videoSet.progress.current)
             },
             timeFormat(t) {
                 var h = Math.floor(t / 3600);
@@ -287,8 +297,8 @@
             },
             // 获取缓存时间
             getLoadTime() {
-                // console.log('缓存了...',this.videoElm.buffered.end(0));
-                this.videoSet.loaded = (this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
+                if (this.videoSet.loaded)
+                    this.videoSet.loaded = (this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
             },
             getTime() {
                 this.videoElm.addEventListener('durationchange', e => {
@@ -302,7 +312,6 @@
             // 拖动播放进度
             touchSlidSrart(e) { },
             touchSlidMove(e) {
-                console.log("触摸中...");
                 let currentX = e.targetTouches[0].pageX;
                 let offsetX = currentX - this.progressBar.pos.left;
                 // 边界检测
@@ -320,7 +329,6 @@
 
             },
             touchSlidEnd(e) {
-                console.log("触摸结束...");
                 let currentX = e.changedTouches[0].pageX;
                 let offsetX = currentX - this.progressBar.pos.left;
                 this.videoSet.progress.current = offsetX;