ソースを参照

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

e 7 年 前
コミット
bcad8c58ce
7 ファイル変更611 行追加18 行削除
  1. 10 4
      README.md
  2. 3 3
      config.json
  3. 2 1
      package.json
  4. BIN
      src/asset/img/demo/choose.png
  5. 111 0
      src/demo/choose.vue
  6. 311 6
      src/package/choose/src/choose.vue
  7. 174 4
      src/view/choose.vue

+ 10 - 4
README.md

@@ -11,6 +11,10 @@
 
 
 > 基于Vue 2.0的移动端轻量级UI组件库
 > 基于Vue 2.0的移动端轻量级UI组件库
 
 
+<p align="center">
+    <img alt="" src="http://nutui.jd.com/asset/img/erweima.jpg">
+</p>
+
 # 安装
 # 安装
 
 
 ``` bash
 ``` bash
@@ -20,10 +24,10 @@ npm install @nutui/nutui --save
 
 
 #### 引用完整组件库
 #### 引用完整组件库
 ``` bash
 ``` bash
-1在入口文件(如app.js)中引入
+1在入口文件(如app.js)中引入
 import NutUI from '@nutui/nutui'
 import NutUI from '@nutui/nutui'
 
 
-2初始化
+2初始化
 NutUI.install(Vue)
 NutUI.install(Vue)
 ```
 ```
 通过以上步骤即可完成整个NutUI组件库的安装。
 通过以上步骤即可完成整个NutUI组件库的安装。
@@ -39,7 +43,9 @@ npm run custom
 
 
 3, 在出现的组件列表中,选择所有您需要打包的组件,然后按下回车键即开始构建
 3, 在出现的组件列表中,选择所有您需要打包的组件,然后按下回车键即开始构建
 
 
-4,片刻之后,自定义构建出的nutui.js文件会出现在dist目录下。在项目中引入和初始化的操作同上
+4,片刻之后,自定义构建出的nutui.js文件会出现在dist目录下
+
+5,在项目中引入和初始化的操作同上
 ```
 ```
 
 
 # 组件用法
 # 组件用法
@@ -47,7 +53,7 @@ npm run custom
 *  一类是扩展 HTML 元素,典型的Vue组件形式,使用方式类似原生HTML元素。
 *  一类是扩展 HTML 元素,典型的Vue组件形式,使用方式类似原生HTML元素。
 ``` bash
 ``` bash
 如遮罩层(Mask)组件,直接使用nut-mask标签即可
 如遮罩层(Mask)组件,直接使用nut-mask标签即可
-<nut-mask :visible.sync="true"><nut-mask>
+<nut-mask :visible.sync="maskShow"><nut-mask>
 ```
 ```
 *  另一类是Vue构造器的扩展组件,使用方式类似jQuery/Zepto方法。
 *  另一类是Vue构造器的扩展组件,使用方式类似jQuery/Zepto方法。
 ``` bash
 ``` bash

+ 3 - 3
config.json

@@ -1,5 +1,5 @@
 {
 {
-  "version": "1.2.0",
+  "version": "1.2.5",
   "packages": [
   "packages": [
     {
     {
       "name": "DatePicker",
       "name": "DatePicker",
@@ -280,8 +280,8 @@
     },
     },
     {
     {
       "name": "Choose",
       "name": "Choose",
-      "chnName": "抽屉式选择(含地址选�)",
-      "desc": "多用于地址选择,可配置参数",
+      "chnName": "抽屉式选择(地址级联)",
+      "desc": "多用于地址选择,每一层级的列表参数需在调用时自定义",
       "type": "component",
       "type": "component",
       "showDemo": true
       "showDemo": true
     }
     }

+ 2 - 1
package.json

@@ -1,9 +1,10 @@
 {
 {
   "name": "@nutui/nutui",
   "name": "@nutui/nutui",
   "description": "基于Vue2的移动端UI组件库",
   "description": "基于Vue2的移动端UI组件库",
-  "version": "1.2.3",
+  "version": "1.2.5",
   "author": "jdc-fe",
   "author": "jdc-fe",
   "main": "dist/nutui.js",
   "main": "dist/nutui.js",
+  "keywords": ["nutui", "vue", "webpack", "vue component","jdc"],
   "repository": {
   "repository": {
     "type": "git",
     "type": "git",
     "url": "https://github.com/jdf2e/nutui.git"
     "url": "https://github.com/jdf2e/nutui.git"

BIN
src/asset/img/demo/choose.png


+ 111 - 0
src/demo/choose.vue

@@ -0,0 +1,111 @@
+<template>
+    <div>
+        <nut-demoheader 
+        :name="$route.name"
+        ></nut-demoheader>
+        <br>
+        <div>
+            <a href="javascript:;" class="button button-primary" @click="showChoose = true">点我出现</a>
+        </div>
+        <nut-choose 
+        :visibile="showChoose"
+        :needCache="true"
+        @init-choose="initChoose" 
+        @close-choose="closeChoose" 
+        @choose-item="closeItem"
+        :listData="chooseData"></nut-choose>       
+    </div>
+
+
+</template>
+
+<script>
+import jsonp from 'jsonp';
+
+export default {
+    data(){
+      return {
+        showChoose: false,
+        loading: false,
+        chooseData: []
+      }
+    },
+    methods:{
+        initChoose() {
+            this.chooseData = [{ 'name': '北京', 'id': 1 },
+                { 'name': '上海', 'id': 2 },
+                { 'name': '天津', 'id': 3 },
+                { 'name': '重庆', 'id': 4 },
+                { 'name': '河北', 'id': 5 },
+                { 'name': '山西', 'id': 6 },
+                { 'name': '河南', 'id': 7 },
+                { 'name': '辽宁', 'id': 8 },
+                { 'name': '吉林', 'id': 9 },
+                { 'name': '黑龙江', 'id': 10 },
+                { 'name': '内蒙古', 'id': 11 },
+                { 'name': '江苏', 'id': 12 },
+                { 'name': '山东', 'id': 13 },
+                { 'name': '安徽', 'id': 14 },
+                { 'name': '浙江', 'id': 15 },
+                { 'name': '福建', 'id': 16 },
+                { 'name': '湖北', 'id': 17 },
+                { 'name': '湖南', 'id': 18 },
+                { 'name': '广东', 'id': 19 },
+                { 'name': '广西', 'id': 20 },
+                { 'name': '江西', 'id': 21 },
+                { 'name': '四川', 'id': 22 },
+                { 'name': '海南', 'id': 23 },
+                { 'name': '贵州', 'id': 24 },
+                { 'name': '云南', 'id': 25 },
+                { 'name': '西藏', 'id': 26 },
+                { 'name': '陕西', 'id': 27 },
+                { 'name': '甘肃', 'id': 28 },
+                { 'name': '青海', 'id': 29 },
+                { 'name': '宁夏', 'id': 30 },
+                { 'name': '新疆', 'id': 31 },
+                { 'name': '台湾', 'id': 32 }];
+        },
+        closeChoose() {
+            this.showChoose = false;
+            console.log('关闭了弹框');
+        },
+        closeItem(item,level) {
+            console.log('当前选中的数据:');
+            console.log(item);
+            let self = this;
+            if(level == 1) {
+                self.chooseData = [
+                    {
+                    "id": 2816,
+                    "name": "密云区"
+                    },
+                    {
+                    "id": 72,
+                    "name": "朝阳区"
+                    }
+                ];
+            }
+            if(level == 2) {
+                self.closeChoose();
+            }
+            //以下注释的代码为地址数据的调用方式,注释打开即可使用,访问url可联系组件开发人员
+            /*if(self.loading) return;//一定要注意防止快速点击问题
+            self.loading = true;//一定要注意防止快速点击问题
+            jsonp(`//xxxxxxxx?fid=${item.id}`, {
+                param: 'callback'
+            }, function(err, data) {
+                self.loading = false;//一定要注意防止快速点击问题
+                if(data.length == 0 ) {
+                    self.closeChoose();//关闭
+                } else {
+                    self.chooseData = data;
+                }
+            });*/
+        }
+    }
+}
+</script>
+
+<style>
+
+</style>

+ 311 - 6
src/package/choose/src/choose.vue

@@ -1,23 +1,328 @@
 <template>
 <template>
-    <div class="nut-choose">
-    <nut-mask 
-		:visible.sync="maskShow"
-		></nut-mask>
+
+    <div class="nut-choose" v-show="visibile">
+        <transition name="maskfade">
+            <div class="mask" @click="maskClose" v-show="visibile"></div>
+        </transition>
+        <transition name="popup">
+            <div :class="{area:true,'short-area':short}" @click.stop v-show="visibile">
+                <div class="area-title">
+                     <span class="area-title-txt">{{ title }}</span>
+                     <a href='javascript:;' class='area-close' @click="maskClose">
+                        <svg>
+                            <line x1='0' y1='0' x2='10' y2='10' className='line' />
+                            <line x1='10' y1='0' x2='0' y2='10' className='line' />
+                        </svg>
+                    </a>
+                </div>
+                <div class="area-con">
+                    <ul class="area-tab-tit">
+                        <li v-for="(data, index) in tempDatas" 
+                            :class="{curr:tabIndex == index + 1,red:!data.item||!data.item[contentKey]}"
+                            @click="getCurrList(index)">
+                                {{data.item && data.item[contentKey]||'请选择'}}
+                            </li>
+                        </li>
+                    </ul>
+                    <div class="area-tab-con">
+                        <ul>
+                            <li v-for="item in list" :class="{curr:item[onlyKey] == currItem[onlyKey]}" @click="getNextList(item)">{{item[contentKey]}}</li>
+                        </ul>
+                    </div>
+                </div>
+            </div>
+        </transition>
+    
     </div>
     </div>
+
 </template>
 </template>
 <script>
 <script>
+
 export default {
 export default {
     name:'nut-choose',
     name:'nut-choose',
     props: {
     props: {
+        visibile: {
+            type: Boolean,
+            default: false
+        },
+        needCache: {
+            type: Boolean,
+            default: false
+        },
+        title:{
+            type: String,
+            default: '所在地区'
+        },
+        listData:{
+            type:Array,
+            default:[],
+        },
+        onlyKey: {
+            type: String,
+            default: 'id'
+        },
+        contentKey: {
+            type: String,
+            default: 'name'
+        },
+        short:{
+            type:Boolean,
+            default:false,
+        }
+    },
+    mounted() {
+        if(this.needCache) {
+            this.$emit('init-choose');
+        }
+    },
+    destroyed(){
+        this.timer = null;
     },
     },
     data() {
     data() {
         return {
         return {
-        	maskShow: false
+            timer:null,
+            areaShow:false,
+            list:[], 
+            tempDatas:[],
+            tabIndex:0,
+            currItem:{},
         };
         };
     },
     },
+    watch:{
+        'visibile'(val,oldVal){
+            if(!val) {
+                this.$emit('close-choose');
+                if(!this.needCache) {
+                    this.resetData();
+                }
+            } else {
+                if(!this.needCache) {
+                    this.$emit('init-choose');
+                }
+            }
+        },
+        'listData'(val,oldVal){
+            if(val){
+                this.list = val;
+                if(this.tabIndex < this.tempDatas.length){
+                   this.tempDatas =  this.tempDatas.slice(0,this.tabIndex);
+                }
+                this.tempDatas.push({
+                    list:val,
+                    item:{}
+                });
+                this.tabIndex += 1;
+            }
+        }
+    },
     methods: {
     methods: {
-    }
+        maskClose() {
+            clearTimeout(this.timer);
+            this.timer = setTimeout(()=>{
+                if(!this.needCache) {
+                    this.resetData();
+                }
+                this.$emit('close-choose');
+            },400);
+        },
+        resetData() {
+            this.list = [];
+            this.tempDatas = [];
+            this.tabIndex = 0;
+            this.currItem = {};
+        },
+        getNextList(item){
+            this.tempDatas[this.tabIndex-1].item = item;
+            this.$emit('choose-item',item,this.tabIndex);
+        },
+        getCurrList(index){
+            this.list = this.tempDatas[index].list || [];
+            this.currItem = this.tempDatas[index].item ;
+            this.tabIndex = index + 1;
+        }
+    },
+
 }
 }
 </script>
 </script>
 <style lang="scss">
 <style lang="scss">
+
+@keyframes popupEnter {
+    from {
+        transform:translate3d(0,100%,0);
+        -webkit-transform:translate3d(0,100%,0);
+    }
+
+    to {
+        transform:translate3d(0,0,0);
+        -webkit-transform:translate3d(0,0,0);
+    }
+}
+@keyframes popupLeave {
+    from {
+        transform:translate3d(0,0,0);
+        -webkit-transform:translate3d(0,0,0);
+    }
+
+    to {
+        transform:translate3d(0,100%,0);
+        -webkit-transform:translate3d(0,100%,0);
+    }
+}
+
+.popup-leave-active{
+    animation: popupLeave 0.4s;
+}
+.popup-enter-active{
+    animation: popupEnter 0.4s;
+}
+.maskfade-enter-active, .maskfade-leave-active {
+  transition: opacity .4s ease;
+}
+.maskfade-enter,.maskfade-leave-active {
+  opacity: 0
+}
+
+.nut-choose {
+
+    .mask{
+        position:fixed;
+        top:0;
+        right:0;
+        bottom:0;
+        left:0;
+        background:rgba(0,0,0,0.7);
+        z-index:99;
+    }
+    ul {
+        margin: 0;
+        padding: 0;
+    }
+    .area {
+        background: #fff;
+        position: fixed;
+        width: 100%;
+        height: 8rem;
+        bottom: 0;
+        left: 0;
+        font-size: .14rem;
+        z-index:999;
+    }
+    .short-area{
+        height:6rem;
+        .area-tab-con {
+            height:4.4rem;
+        }
+    }
+
+    .area-title {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background: #f3f2f8;
+        height: .84rem;
+        line-height: .84rem;
+        text-align: center;
+        position: relative;
+        .area-title-txt{
+            font-size:16px;
+        }
+    }
+    .area-close {
+        position: absolute;
+        right: 0;
+        display: inline-block;
+        width: 40px;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 20px;
+        text-align: center;
+        text-decoration: none;
+        svg {
+            width: 10px;
+            height: 12px;
+        }
+        line {
+            stroke: #6a6f7b;
+            stroke-width: 1px;
+        }
+    }
+    .area-con {}
+    .area-tab-tit {
+        position: relative;
+        height: .8rem;
+        font-size:14px;
+        &:after {
+            content: '';
+            position: absolute;
+            left: 0;
+            bottom: 0;
+            width: 200%;
+            height: 0;
+            box-sizing: border-box;
+            transform: scale(0.5);
+            transform-origin: left bottom;
+            border-bottom: 1px solid #ececee;
+        }
+        li {
+            float: left;
+            height: .8rem;
+            line-height: .8rem;
+            display: flex;
+            align-items: center;
+            margin-left: .2rem;
+            &.red{
+                color: #e4393c;
+            }
+            &.curr {
+                //color: #e4393c;
+                position: relative;
+                // border-bottom: 1px solid #e4393c;
+                 &:after {
+                    content: '';
+                    position: absolute;
+                    left: 0;
+                    bottom: 0;
+                    width: 200%;
+                    height: 0;
+                    box-sizing: border-box;
+                    transform: scale(0.5);
+                    transform-origin: left bottom;
+                    border-bottom: 1px solid #e4393c;
+                }
+                
+            }
+        }
+    }
+    .area-tab-con {
+        height: 6.4rem;
+        overflow-y: auto;
+        font-size:14px;
+        -webkit-overflow-scrolling:touch;
+        li {
+            display: flex;
+            align-items: center;
+            height: .8rem;
+            line-height: .8rem;
+            position: relative;
+            padding-left: .2rem;
+            &.curr {
+                position: relative;
+                color: #e4393c;
+                &:before {
+                    content: '';
+                    position: absolute;
+                    right: .2rem;
+                    top: 50%;
+                    margin-top: -.1rem;
+                    width: .26rem;
+                    height: .18rem;
+                    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAJCAYAAAGefZb8AAAAAXNSR0IArs4c6QAAAItJREFUGBljYMAKPpuaajP8MDBQBct+MjDwBzGAdBWK8v+hocwM/42N+cEMFClsHJAqFDNABv+3tBRCEcSmEyT2ydBwEYbcZ0PDpWDBzwYGR2CycEG4AFASQxAmSRYN8grIRLjLPxsZNYBCAptpGIqRFYHCAOR4mGa8ipE1gthgzYaGr+DOQFcA5QMACe4+MqIvCpoAAAAASUVORK5CYII=) no-repeat;
+                    background-size: cover;
+                }
+            }
+        }
+    }
+}
 </style>
 </style>

+ 174 - 4
src/view/choose.vue

@@ -1,12 +1,106 @@
 <template>
 <template>
     <div>
     <div>
         <!-- 组件名和描述 -->
         <!-- 组件名和描述 -->
-        <nut-demoheader 
+        <nut-docheader 
         :name="$route.name"
         :name="$route.name"
-        ></nut-demoheader>
+        :chName="$route.params.chnName" 
+        type="Component" 
+        :showQrCode="true"
+        ></nut-docheader>
 
 
-        <!-- DEMO区域 -->
-        <!-- <nut-switch :height="30" :width="60" @switch-on="switchOn" @switch-off="switchOff"></nut-switch> -->
+        <h5>示例</h5>
+        <h6>基本用法</h6>
+        <nut-codebox :code="demo1" imgUrl="../asset/img/demo/choose.png"></nut-codebox>
+        <h6>事件</h6>
+        <nut-codebox :code="demo2"></nut-codebox>
+        <h5>Props</h5>
+        <div class="tbl-wrapper">
+        <table class="u-full-width">
+          <thead>
+            <tr>
+              <th>参数</th>
+              <th>说明</th>
+              <th>类型</th>
+              <th>默认值</th>
+              <th>可选值</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr>
+              <td>visibile</td>
+              <td>打开和关闭选择弹层</td>
+              <td>Boolean</td>
+              <td>false</td>
+              <td>true</td>
+            </tr>
+            <tr>
+              <td>needCache</td>
+              <td>弹层打开后再关闭是否需要缓存下来数据,以备下次打开使用</td>
+              <td>Boolean</td>
+              <td>false</td>
+              <td>true</td>
+            </tr>
+            <tr>
+              <td>title</td>
+              <td>选择弹层标题</td>
+              <td>String</td>
+              <td>所在地区</td>
+              <td>--</td>
+            </tr>
+            <tr>
+              <td>onlyKey</td>
+              <td>列表数据对象中,区分每条数据的key名,如'id'</td>
+              <td>String</td>
+              <td>id</td>
+              <td>--</td>
+            </tr>
+            <tr>
+              <td>contentKey</td>
+              <td>列表数据对象中,用于显示到列表中的字段key名,如'name'</td>
+              <td>String</td>
+              <td>name</td>
+              <td>--</td>
+            </tr>
+            <tr>
+              <td>listData</td>
+              <td>弹层列表数据</td>
+              <td>Array</td>
+              <td>[]</td>
+              <td>--</td>
+            </tr>
+            
+          </tbody>
+        </table>
+        </div>
+        <h5>Events</h5>
+        <div class="tbl-wrapper">
+        <table class="u-full-width">
+          <thead>
+            <tr>
+              <th>事件名</th>
+              <th>说明</th>
+              <th>回调参数</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr>
+              <td>init-choose</td>
+              <td>打开选择弹层时给列表初始化数据入口</td>
+              <td>--</td>
+            </tr>
+            <tr>
+              <td>close-choose</td>
+              <td>关闭选择弹层时的回调</td>
+              <td>--</td>
+            </tr>
+            <tr>
+              <td>choose-item</td>
+              <td>选择某一条选项时的回调</td>
+              <td>item:当前选中的数据,index: 当前操作的所处层级</td>
+            </tr>
+          </tbody>
+        </table>
+        </div>
     </div>
     </div>
 </template>
 </template>
 
 
@@ -14,6 +108,82 @@
 export default {
 export default {
     data(){
     data(){
         return{
         return{
+            demo1:`<nut-choose 
+        :visibile="showChoose"
+        :needCache="true"
+        @init-choose="initChoose" 
+        @close-choose="closeChoose" 
+        @choose-item="closeItem"
+        :listData="chooseData"></nut-choose> `,
+            demo2: `export default {
+    data(){
+      return {
+        showChoose: false,
+        loading: false,
+        chooseData: []
+      }
+    },
+    methods:{
+        initChoose() {
+            this.chooseData = [{ 'name': '北京', 'id': 1 },
+                { 'name': '上海', 'id': 2 },
+                { 'name': '天津', 'id': 3 },
+                { 'name': '重庆', 'id': 4 },
+                { 'name': '河北', 'id': 5 },
+                { 'name': '山西', 'id': 6 },
+                { 'name': '河南', 'id': 7 },
+                { 'name': '辽宁', 'id': 8 },
+                { 'name': '吉林', 'id': 9 },
+                { 'name': '黑龙江', 'id': 10 },
+                { 'name': '内蒙古', 'id': 11 },
+                { 'name': '江苏', 'id': 12 },
+                { 'name': '山东', 'id': 13 },
+                { 'name': '安徽', 'id': 14 },
+                { 'name': '浙江', 'id': 15 },
+                { 'name': '福建', 'id': 16 },
+                { 'name': '湖北', 'id': 17 },
+                { 'name': '湖南', 'id': 18 },
+                { 'name': '广东', 'id': 19 },
+                { 'name': '广西', 'id': 20 },
+                { 'name': '江西', 'id': 21 },
+                { 'name': '四川', 'id': 22 },
+                { 'name': '海南', 'id': 23 },
+                { 'name': '贵州', 'id': 24 },
+                { 'name': '云南', 'id': 25 },
+                { 'name': '西藏', 'id': 26 },
+                { 'name': '陕西', 'id': 27 },
+                { 'name': '甘肃', 'id': 28 },
+                { 'name': '青海', 'id': 29 },
+                { 'name': '宁夏', 'id': 30 },
+                { 'name': '新疆', 'id': 31 },
+                { 'name': '台湾', 'id': 32 }];
+        },
+        closeChoose() {
+            this.showChoose = false;
+            console.log('关闭了弹框');
+        },
+        closeItem(item,level) {
+            console.log('当前选中的数据:');
+            console.log(item);
+            let self = this;
+            if(level == 1) {
+                self.chooseData = [
+                    {
+                    "id": 2816,
+                    "name": "密云区"
+                    },
+                    {
+                    "id": 72,
+                    "name": "朝阳区"
+                    }
+                ];
+            }
+            if(level == 2) {
+                self.closeChoose();
+            }
+        }
+    }
+}`
         }
         }
     },
     },
     methods:{
     methods:{