mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'master' of gitlab.qima-inc.com:fe/zanui-vue
This commit is contained in:
commit
a8d75dc0ab
78
README.md
78
README.md
@ -1,35 +1,61 @@
|
||||
## 下载项目
|
||||
```bash
|
||||
git@gitlab.qima-inc.com:fe/zanui-vue.git
|
||||
cd zanui-vue
|
||||
<p>
|
||||
<a href="https://github.com/youzan/"><img alt="有赞logo" width="36px" src="https://img.yzcdn.cn/public_files/2017/02/09/e84aa8cbbf7852688c86218c1f3bbf17.png" alt="youzan">
|
||||
</p></a>
|
||||
<p align="center">
|
||||
<img alt="项目logo" src="https://img.yzcdn.cn/public_files/2017/02/06/ee0ebced79a80457d77ce71c7d414c74.png">
|
||||
</p>
|
||||
<p align="center">Vue Mobile UI at YouZan</p>
|
||||
|
||||
## 一、安装
|
||||
|
||||
```shell
|
||||
ynpm install @youzan/zanui-vue
|
||||
```
|
||||
|
||||
## 二、使用
|
||||
|
||||
|
||||
### 1. 导入所有组件
|
||||
|
||||
```javascript
|
||||
import Vue from 'vue';
|
||||
import ZanUI from '@youzan/zanui-vue';
|
||||
// 你也可以使用自己的主题
|
||||
import '@youzan/zanui-vue/lib/zanui-css/index.css';
|
||||
|
||||
Vue.use(ZanUI);
|
||||
```
|
||||
|
||||
### 2. 按需导入组件
|
||||
|
||||
```javascript
|
||||
import Vue from 'vue';
|
||||
import { Button, Cell } from '@youzan/zanui-vue';
|
||||
import '@youzan/zanui-vue/lib/zanui-css/button.css';
|
||||
import '@youzan/zanui-vue/lib/zanui-css/cell.css';
|
||||
|
||||
Vue.component(Button.name, Button);
|
||||
Vue.component(Cell.name, Cell);
|
||||
```
|
||||
|
||||
## 安装组件依赖库
|
||||
```bash
|
||||
ynpm i
|
||||
## 三、开发
|
||||
|
||||
### 1. 新建一个组件
|
||||
|
||||
```shell
|
||||
make init componentName
|
||||
```
|
||||
|
||||
## 新建组件(以waterfall为例)
|
||||
新建一个Vue组件,比如 waterfall
|
||||
```bash
|
||||
make init waterfall
|
||||
```
|
||||
就可以在 packages目录 里面看到waterfall初始化的组件代码了。记得更新package.json和README.md里的组件描述信息
|
||||
### 2. 示例预览
|
||||
|
||||
## 示例预览(以waterfall为例)
|
||||
在 docs/nav.config.json 文件里合适的地方写入组件声明,根据组件类型(JS组件,CSS组件,Form等)进行区分
|
||||
在 docs/examples 目录里新建 同名的md文件,如 waterfall.md
|
||||
在项目的根目录下执行以下命令,启动server
|
||||
```
|
||||
在`docs/nav.config.json`文件里合适的地方写入组件声明,根据组件类型(JS组件,CSS组件,Form等)进行区分 在`docs/examples-docs`目录里新建同名的md文件,如`waterfall.md`,在项目的根目录下执行以下命令,启动server:
|
||||
|
||||
```shell
|
||||
make dev
|
||||
```
|
||||
浏览器访问 http://localhost:8080/#/ 就可以看到所有组件的示例了
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
浏览器访问[http://localhost:8080](http://localhost:8080)就可以看到所有组件的示例了。
|
||||
|
||||
## 四、开源协议
|
||||
|
||||
本项目基于 [MIT](https://zh.wikipedia.org/wiki/MIT%E8%A8%B1%E5%8F%AF%E8%AD%89) 协议,请自由地享受和参与开源。
|
||||
|
@ -5,6 +5,10 @@ delete config.devtool;
|
||||
|
||||
config.entry = Components;
|
||||
|
||||
config.externals = {
|
||||
vue: 'vue'
|
||||
};
|
||||
|
||||
config.output = {
|
||||
path: './lib',
|
||||
filename: '[name].js',
|
||||
|
@ -42,7 +42,9 @@ module.exports = {
|
||||
'vue$': 'vue/dist/vue.runtime.common.js',
|
||||
'zanui': path.join(__dirname, '..'),
|
||||
'src': path.join(__dirname, '../src'),
|
||||
'packages': path.join(__dirname, '../packages')
|
||||
'packages': path.join(__dirname, '../packages'),
|
||||
'lib': path.join(__dirname, '../lib'),
|
||||
'components': path.join(__dirname, '../docs/components')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
|
@ -22,8 +22,13 @@
|
||||
"badge": "./packages/badge/index.js",
|
||||
"search": "./packages/search/index.js",
|
||||
"step": "./packages/step/index.js",
|
||||
"tabs": "./packages/tabs/index.js",
|
||||
"tab": "./packages/tab/index.js",
|
||||
"lazyload": "./packages/lazyload/index.js",
|
||||
"image-preview": "./packages/image-preview/index.js",
|
||||
"col": "./packages/col/index.js",
|
||||
"row": "./packages/row/index.js",
|
||||
"actionsheet": "./packages/actionsheet/index.js"
|
||||
"actionsheet": "./packages/actionsheet/index.js",
|
||||
"quantity": "./packages/quantity/index.js",
|
||||
"progress": "./packages/progress/index.js"
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ export default {
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
section > h3 {
|
||||
font-size: 22px;
|
||||
margin: 23px 0;
|
||||
}
|
||||
@ -72,6 +72,12 @@ export default {
|
||||
color: #5e6d82;
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
p > code {
|
||||
background-color: #eee;
|
||||
padding: 2px 4px;
|
||||
color: #26a2ff;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-page {
|
||||
|
8
docs/build/0.js
vendored
8
docs/build/0.js
vendored
File diff suppressed because one or more lines are too long
2
docs/build/1.js
vendored
2
docs/build/1.js
vendored
@ -1 +1 @@
|
||||
webpackJsonp([1],{212:function(t,e,a){a(358);var i=a(0)(a(225),a(317),null,null);t.exports=i.exports},225:function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(24),s=i(n);e.default={data:function(){return{highlights:[],navState:[],data:s.default["zh-CN"],base:"/component"}}}},259:function(t,e,a){e=t.exports=a(15)(),e.push([t.i,".side-nav{width:100%;box-sizing:border-box;padding:40px 20px;background:#f9fafb}.side-nav li{list-style:none}.side-nav ul{padding:0;margin:0;overflow:hidden}.side-nav .nav-item a{font-size:16px;color:#5e6d82;line-height:40px;height:40px;margin:0;padding:0;text-decoration:none;display:block;position:relative;-webkit-transition:all .3s;transition:all .3s}.side-nav .nav-item a.active{color:#20a0ff}.side-nav .nav-item .nav-item a{display:block;height:40px;line-height:40px;font-size:13px;padding-left:24px}.side-nav .nav-item .nav-item a:hover{color:#20a0ff}.side-nav .nav-group__title{font-size:12px;color:#99a9bf;padding-left:8px;line-height:26px;margin-top:10px}",""])},317:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"side-nav"},[a("ul",t._l(t.data,function(e){return a("li",{staticClass:"nav-item"},[e.path?a("router-link",{attrs:{"active-class":"active",to:t.base+e.path,exact:""},domProps:{textContent:t._s(e.title||e.name)}}):a("a",[t._v(t._s(e.name))]),t._v(" "),e.children?a("ul",{staticClass:"pure-menu-list sub-nav"},t._l(e.children,function(e){return a("li",{staticClass:"nav-item"},[a("router-link",{attrs:{"active-class":"active",to:t.base+e.path},domProps:{textContent:t._s(e.title||e.name)}})],1)})):t._e(),t._v(" "),e.groups?t._l(e.groups,function(e){return a("div",{staticClass:"nav-group"},[a("div",{staticClass:"nav-group__title"},[t._v(t._s(e.groupName))]),t._v(" "),a("ul",{staticClass:"pure-menu-list"},[t._l(e.list,function(e){return[e.disabled?t._e():a("li",{staticClass:"nav-item"},[a("router-link",{attrs:{"active-class":"active",to:t.base+e.path},domProps:{textContent:t._s(e.title)}})],1)]})],2)])}):t._e()],2)}))])},staticRenderFns:[]}},358:function(t,e,a){var i=a(259);"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);a(25)("1517d9c0",i,!0)}});
|
||||
webpackJsonp([1],{229:function(t,e,a){a(425);var i=a(0)(a(243),a(373),null,null);t.exports=i.exports},243:function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(24),s=i(n);e.default={data:function(){return{highlights:[],navState:[],data:s.default["zh-CN"],base:"/component"}}}},287:function(t,e,a){e=t.exports=a(15)(),e.push([t.i,".side-nav{width:100%;box-sizing:border-box;padding:40px 20px;background:#f9fafb}.side-nav li{list-style:none}.side-nav ul{padding:0;margin:0;overflow:hidden}.side-nav .nav-item a{font-size:16px;color:#5e6d82;line-height:40px;height:40px;margin:0;padding:0;text-decoration:none;display:block;position:relative;-webkit-transition:all .3s;transition:all .3s}.side-nav .nav-item a.active{color:#20a0ff}.side-nav .nav-item .nav-item a{display:block;height:40px;line-height:40px;font-size:13px;padding-left:24px}.side-nav .nav-item .nav-item a:hover{color:#20a0ff}.side-nav .nav-group__title{font-size:12px;color:#99a9bf;padding-left:8px;line-height:26px;margin-top:10px}",""])},373:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"side-nav"},[a("ul",t._l(t.data,function(e){return a("li",{staticClass:"nav-item"},[e.path?a("router-link",{attrs:{"active-class":"active",to:t.base+e.path,exact:""},domProps:{textContent:t._s(e.title||e.name)}}):a("a",[t._v(t._s(e.name))]),t._v(" "),e.children?a("ul",{staticClass:"pure-menu-list sub-nav"},t._l(e.children,function(e){return a("li",{staticClass:"nav-item"},[a("router-link",{attrs:{"active-class":"active",to:t.base+e.path},domProps:{textContent:t._s(e.title||e.name)}})],1)})):t._e(),t._v(" "),e.groups?t._l(e.groups,function(e){return a("div",{staticClass:"nav-group"},[a("div",{staticClass:"nav-group__title"},[t._v(t._s(e.groupName))]),t._v(" "),a("ul",{staticClass:"pure-menu-list"},[t._l(e.list,function(e){return[e.disabled?t._e():a("li",{staticClass:"nav-item"},[a("router-link",{attrs:{"active-class":"active",to:t.base+e.path},domProps:{textContent:t._s(e.title)}})],1)]})],2)])}):t._e()],2)}))])},staticRenderFns:[]}},425:function(t,e,a){var i=a(287);"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);a(25)("1517d9c0",i,!0)}});
|
7
docs/build/zanui-docs.js
vendored
7
docs/build/zanui-docs.js
vendored
File diff suppressed because one or more lines are too long
7
docs/build/zanui-examples.js
vendored
7
docs/build/zanui-examples.js
vendored
File diff suppressed because one or more lines are too long
19
docs/components/mobile-computed.js
Normal file
19
docs/components/mobile-computed.js
Normal file
@ -0,0 +1,19 @@
|
||||
import MobilePopup from 'components/mobile-popup.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MobilePopup
|
||||
},
|
||||
|
||||
computed: {
|
||||
mobileUrl() {
|
||||
return location.pathname + 'examples.html' + location.hash;
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
mobileShow: false
|
||||
};
|
||||
}
|
||||
};
|
45
docs/components/mobile-popup.vue
Normal file
45
docs/components/mobile-popup.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<zan-popup v-model="currentValue">
|
||||
<div class="mobile-popup">
|
||||
<iframe :src="url" class="mobile-popup-iframe"></iframe>
|
||||
</div>
|
||||
</zan-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
url: String,
|
||||
value: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentValue(val) {
|
||||
this.$emit('input', val);
|
||||
},
|
||||
value(val) {
|
||||
console.log(val);
|
||||
this.currentValue = val;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.mobile-popup {
|
||||
width: 380px;
|
||||
height: 500px;
|
||||
border: 5px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.mobile-popup-iframe {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
</style>
|
76
docs/examples-dist/actionsheet.vue
Normal file
76
docs/examples-dist/actionsheet.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<template><section class="demo-actionsheet"><h1 class="demo-title">actionsheet</h1><example-block title="基础用法">
|
||||
<div class="zan-row">
|
||||
<zan-button @click="show1 = true">弹出actionsheet</zan-button>
|
||||
</div>
|
||||
<zan-actionsheet v-model="show1" :actions="actions1">
|
||||
</zan-actionsheet>
|
||||
|
||||
</example-block><example-block title="带取消按钮的ActionSheet">
|
||||
<div class="zan-row">
|
||||
<zan-button @click="show2 = true">弹出带取消按钮的actionsheet</zan-button>
|
||||
</div>
|
||||
<zan-actionsheet v-model="show2" :actions="actions1" cancel-text="取消">
|
||||
</zan-actionsheet>
|
||||
|
||||
</example-block><example-block title="带标题的ActionSheet">
|
||||
<div class="zan-row">
|
||||
<zan-button @click="show3 = true">弹出带标题的actionsheet</zan-button>
|
||||
</div>
|
||||
<zan-actionsheet v-model="show3" title="支持以下配送方式" class="title-actionsheet">
|
||||
<p>一些内容</p>
|
||||
</zan-actionsheet>
|
||||
|
||||
</example-block></section></template>
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b actionsheet {
|
||||
.actionsheet-wx {
|
||||
color: #06BF04;
|
||||
}
|
||||
|
||||
.zan-button {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.title-actionsheet p {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
import MobileComputed from 'components/mobile-computed';
|
||||
|
||||
export default {
|
||||
mixins: [MobileComputed],
|
||||
|
||||
data() {
|
||||
return {
|
||||
show1: false,
|
||||
show2: false,
|
||||
show3: false,
|
||||
actions1: [
|
||||
{
|
||||
name: '微信安全支付',
|
||||
className: 'actionsheet-wx'
|
||||
},
|
||||
{
|
||||
name: '支付宝支付',
|
||||
loading: true
|
||||
},
|
||||
{
|
||||
name: '有赞E卡',
|
||||
subname: '(剩余260.50元)'
|
||||
},
|
||||
{
|
||||
name: '信用卡支付'
|
||||
},
|
||||
{
|
||||
name: '其他支付方式'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
@ -3,13 +3,12 @@
|
||||
</zan-card>
|
||||
|
||||
</example-block><example-block title="高级用法">
|
||||
<zan-card title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余" desc="商品SKU1,商品SKU2" thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
|
||||
<zan-card thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
|
||||
<div class="zan-card__row" slot="title">
|
||||
<h4 class="zan-card__title">商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余</h4>
|
||||
<span class="zan-card__price">¥ 2.00</span>
|
||||
</div>
|
||||
<div class="zan-card__row" slot="desc">
|
||||
<h4 class="zan-card__desc">商品sku</h4>
|
||||
<span class="zan-card__num">x 2</span>
|
||||
</div>
|
||||
<div class="zan-card__footer" slot="footer">
|
||||
|
@ -6,12 +6,23 @@
|
||||
|
||||
|
||||
</example-block></section></template>
|
||||
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b dialog {
|
||||
.zan-button {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
import { Dialog } from 'src/index';
|
||||
import MobileComputed from 'components/mobile-computed';
|
||||
|
||||
export default {
|
||||
mixins: [MobileComputed],
|
||||
|
||||
methods: {
|
||||
handleAlertClick() {
|
||||
Dialog.alert({
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template><section class="demo-field"><h1 class="demo-title">field</h1><example-block title="基础用法">
|
||||
<zan-cell-group>
|
||||
<zan-field type="text" label="用户名:" placeholder="请输入用户名"></zan-field>
|
||||
<zan-field type="text" label="用户名:" placeholder="请输入用户名" v-model="username"></zan-field>
|
||||
<zan-field type="password" label="密码:" placeholder="请输入密码"></zan-field>
|
||||
<zan-field type="textarea" label="个人介绍:" placeholder="请输入个人介绍"></zan-field>
|
||||
</zan-cell-group>
|
||||
@ -10,12 +10,25 @@
|
||||
<zan-field type="text" placeholder="请输入用户名"></zan-field>
|
||||
</zan-cell-group>
|
||||
|
||||
</example-block><example-block title="监听change事件">
|
||||
</example-block><example-block title="禁用的输入框">
|
||||
<zan-cell-group>
|
||||
<zan-field type="text" label="用户名:" placeholder="请输入用户名" @change="handleChange"></zan-field>
|
||||
<zan-field label="用户名:" type="text" placeholder="请输入用户名" v-model="username" disabled></zan-field>
|
||||
</zan-cell-group>
|
||||
|
||||
</example-block><example-block title="错误的输入框">
|
||||
<zan-cell-group>
|
||||
<zan-field label="用户名:" type="text" placeholder="请输入用户名" error=""></zan-field>
|
||||
</zan-cell-group>
|
||||
|
||||
</example-block></section></template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);</script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
username: 'zhangmin'
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
33
docs/examples-dist/icon.vue
Normal file
33
docs/examples-dist/icon.vue
Normal file
@ -0,0 +1,33 @@
|
||||
<template><section class="demo-icon"><h1 class="demo-title">icon</h1><example-block title="所有Icon">
|
||||
<zan-icon name="album"></zan-icon>
|
||||
<zan-icon name="arrow"></zan-icon>
|
||||
<zan-icon name="camera"></zan-icon>
|
||||
<zan-icon name="certificate"></zan-icon>
|
||||
<zan-icon name="check"></zan-icon>
|
||||
<zan-icon name="checked"></zan-icon>
|
||||
<zan-icon name="close"></zan-icon>
|
||||
<zan-icon name="gift"></zan-icon>
|
||||
<zan-icon name="home"></zan-icon>
|
||||
<zan-icon name="location"></zan-icon>
|
||||
<zan-icon name="message"></zan-icon>
|
||||
<zan-icon name="send"></zan-icon>
|
||||
<zan-icon name="shopping-cart"></zan-icon>
|
||||
<zan-icon name="sign"></zan-icon>
|
||||
<zan-icon name="store"></zan-icon>
|
||||
<zan-icon name="topay"></zan-icon>
|
||||
<zan-icon name="tosend"></zan-icon>
|
||||
|
||||
</example-block></section></template>
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b icon {
|
||||
|
||||
.zan-icon {
|
||||
margin: 10px;
|
||||
font-size: 45px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);</script>
|
@ -1,6 +1,13 @@
|
||||
<template><section class="demo-picker"><h1 class="demo-title">picker</h1><example-block title="基础用法">
|
||||
<zan-picker :columns="pickerColumns" @change="handlePickerChange"></zan-picker>
|
||||
|
||||
|
||||
|
||||
</example-block><example-block title="带toolbar的Picker">
|
||||
<zan-picker :columns="pickerColumns" show-toolbar="" @change="handlePickerChange" @cancel="handlePickerCancel" @confirm="handlePickerConfirm"></zan-picker>
|
||||
|
||||
|
||||
|
||||
</example-block></section></template>
|
||||
|
||||
<script>
|
||||
@ -30,6 +37,12 @@ export default {
|
||||
methods: {
|
||||
handlePickerChange(picker, values) {
|
||||
picker.setColumnValues(1, citys[values[0]]);
|
||||
},
|
||||
handlePickerCancel() {
|
||||
alert('picker cancel');
|
||||
},
|
||||
handlePickerConfirm() {
|
||||
alert('picker confirm');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
<template><section class="demo-popup"><h1 class="demo-title">popup</h1><example-block title="基础用法">
|
||||
<div class="zan-row">
|
||||
<zan-button @click="popupShow1 = true">从下方弹出popup</zan-button>
|
||||
<zan-button @click="popupShow1 = true;">从下方弹出popup</zan-button>
|
||||
</div>
|
||||
<zan-popup v-model="popupShow1" position="bottom" class="zan-popup-1">
|
||||
xxxx
|
||||
<zan-button @click="showDialog">弹出dialog</zan-button>
|
||||
</zan-popup>
|
||||
|
||||
<div class="zan-row">
|
||||
@ -23,17 +23,55 @@
|
||||
<div class="zan-row">
|
||||
<zan-button @click="popupShow4 = true">从中间弹出popup</zan-button>
|
||||
</div>
|
||||
<zan-popup v-model="popupShow4" transition="popup-fade" class="zan-popup-4">
|
||||
一些内容
|
||||
<zan-popup v-model="popupShow4" class="zan-popup-4">
|
||||
从中间弹出popup
|
||||
</zan-popup>
|
||||
|
||||
|
||||
|
||||
</example-block></section></template>
|
||||
|
||||
</example-block></section></template>
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b popup {
|
||||
.zan-popup-1 {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.zan-popup-2 {
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, 0.701961);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.zan-popup-3 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.zan-popup-4 {
|
||||
width: 60%;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.zan-button {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
import MobileComputed from 'components/mobile-computed';
|
||||
import Dialog from 'packages/dialog';
|
||||
|
||||
export default {
|
||||
mixins: [MobileComputed],
|
||||
|
||||
data() {
|
||||
return {
|
||||
popupShow1: false,
|
||||
@ -51,6 +89,19 @@ export default {
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
showDialog() {
|
||||
Dialog.confirm({
|
||||
title: 'confirm标题',
|
||||
message: '弹窗提示文字,左右始终距离边20PX,上下距离20PX,文字左对齐。弹窗提示文字,左右始终距离边20PX,上下距离20PX,文字左对齐。'
|
||||
}).then((action) => {
|
||||
console.log(action);
|
||||
}, (error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
46
docs/examples-dist/progress.vue
Normal file
46
docs/examples-dist/progress.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<template><section class="demo-progress"><h1 class="demo-title">progress</h1><example-block title="基础用法">
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :percentage="0"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo2" :percentage="46"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :percentage="100"></zan-progress>
|
||||
</div>
|
||||
|
||||
</example-block><example-block title="Inactive">
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :inactive="true" :percentage="0"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo2" :inactive="true" :percentage="46"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :inactive="true" :percentage="100"></zan-progress>
|
||||
</div>
|
||||
</example-block><example-block title="自定义颜色">
|
||||
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" pivot-text="红色" color="#ed5050" :percentage="26"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" pivot-text="橙色" color="#f60" :percentage="46"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" pivot-text="黄色" color="#f09000" :percentage="66"></zan-progress>
|
||||
</div>
|
||||
|
||||
</example-block></section></template>
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b progress {
|
||||
@e wrapper {
|
||||
padding: 5px;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);</script>
|
36
docs/examples-dist/quantity.vue
Normal file
36
docs/examples-dist/quantity.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template><section class="demo-quantity"><h1 class="demo-title">quantity</h1><example-block title="基础用法">
|
||||
<zan-quantity v-model="quantity1"></zan-quantity>
|
||||
<p class="curr-quantity">当前值:{{ quantity1 }}</p>
|
||||
|
||||
</example-block><example-block title="禁用Quantity">
|
||||
<zan-quantity v-model="quantity1" disabled></zan-quantity>
|
||||
|
||||
</example-block><example-block title="高级用法">
|
||||
<zan-quantity v-model="quantity2" min="5" max="40" step="2" default-value="9"></zan-quantity>
|
||||
<p class="curr-quantity">当前值:{{ quantity2 }}</p>
|
||||
|
||||
</example-block></section></template>
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b quantity {
|
||||
.zan-quantity {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.curr-quantity {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
quantity1: 1,
|
||||
quantity2: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
68
docs/examples-dist/tab.vue
Normal file
68
docs/examples-dist/tab.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<template><section class="demo-tab"><h1 class="demo-title">tab</h1><example-block title="基础用法">
|
||||
<zan-tabs>
|
||||
<zan-tab title="选项一">内容一</zan-tab>
|
||||
<zan-tab title="选项二">内容二</zan-tab>
|
||||
<zan-tab title="选项三">内容三</zan-tab>
|
||||
<zan-tab title="选项四">内容四</zan-tab>
|
||||
<zan-tab title="选项五">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
|
||||
</example-block><example-block title="禁用用法">
|
||||
<zan-tabs>
|
||||
<zan-tab title="选项一">内容一</zan-tab>
|
||||
<zan-tab disable="" title="选项二" @disable="popalert">内容二</zan-tab>
|
||||
<zan-tab title="选项三">内容三</zan-tab>
|
||||
<zan-tab title="选项四">内容四</zan-tab>
|
||||
<zan-tab title="选项五">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
|
||||
|
||||
</example-block><example-block title="card样式用法">
|
||||
<zan-tabs type="card">
|
||||
<zan-tab title="选项一">内容一</zan-tab>
|
||||
<zan-tab title="选项二">内容二</zan-tab>
|
||||
<zan-tab title="选项三">内容三</zan-tab>
|
||||
<zan-tab title="选项四">内容四</zan-tab>
|
||||
<zan-tab title="选项五">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
|
||||
</example-block><example-block title="自定义样式用法">
|
||||
<zan-tabs active="2" navclass="custom-tabwrap">
|
||||
<zan-tab title="选项一" class="custom-pane">内容一</zan-tab>
|
||||
<zan-tab title="选项二" class="custom-pane">内容二</zan-tab>
|
||||
<zan-tab title="选项三" class="custom-pane">内容三</zan-tab>
|
||||
<zan-tab title="选项四" class="custom-pane">内容四</zan-tab>
|
||||
<zan-tab title="选项五" class="custom-pane">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
|
||||
|
||||
</example-block></section></template>
|
||||
<style>
|
||||
.page-tab {
|
||||
padding: 0 15px;
|
||||
}
|
||||
.custom-tabwrap .zan-tab-active{
|
||||
color: #20a0ff;
|
||||
}
|
||||
.custom-tabwrap .zan-tabs-nav-bar{
|
||||
background: #20a0ff;
|
||||
}
|
||||
.custom-tab {
|
||||
font-weight: bold;
|
||||
}
|
||||
.custom-pane {
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
export default {
|
||||
methods: {
|
||||
popalert() {
|
||||
alert('haha')
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -10,9 +10,49 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</example-block></section></template>
|
||||
|
||||
<style>
|
||||
.waterfall {
|
||||
max-height: 300px;
|
||||
overflow: scroll;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);</script>
|
||||
import Vue from "vue";import ExampleBlock from "../components/example-block";Vue.component("example-block", ExampleBlock);
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [1, 2, 3, 4, 5],
|
||||
loading: false,
|
||||
finished: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
loadMore() {
|
||||
if (this.list.length >= 200) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
setTimeout(() => {
|
||||
let lastNumber = this.list[this.list.length - 1];
|
||||
for (let i = 0; i < 5; i ++) {
|
||||
lastNumber += 1;
|
||||
this.list.push(lastNumber);
|
||||
}
|
||||
this.loading = false;
|
||||
}, 2500);
|
||||
},
|
||||
loadMoreUpper() {
|
||||
if (this.list[0] < 0) return;
|
||||
this.list.unshift(-1);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isWaterfallDisabled: function() {
|
||||
return this.loading || this.finished;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
118
docs/examples-docs/actionsheet.md
Normal file
118
docs/examples-docs/actionsheet.md
Normal file
@ -0,0 +1,118 @@
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b actionsheet {
|
||||
.actionsheet-wx {
|
||||
color: #06BF04;
|
||||
}
|
||||
|
||||
.zan-button {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.title-actionsheet p {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import MobileComputed from 'components/mobile-computed';
|
||||
|
||||
export default {
|
||||
mixins: [MobileComputed],
|
||||
|
||||
data() {
|
||||
return {
|
||||
show1: false,
|
||||
show2: false,
|
||||
show3: false,
|
||||
actions1: [
|
||||
{
|
||||
name: '微信安全支付',
|
||||
className: 'actionsheet-wx'
|
||||
},
|
||||
{
|
||||
name: '支付宝支付',
|
||||
loading: true
|
||||
},
|
||||
{
|
||||
name: '有赞E卡',
|
||||
subname: '(剩余260.50元)'
|
||||
},
|
||||
{
|
||||
name: '信用卡支付'
|
||||
},
|
||||
{
|
||||
name: '其他支付方式'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
## ActionSheet
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<div class="zan-row">
|
||||
<zan-button @click="show1 = true">弹出actionsheet</zan-button>
|
||||
</div>
|
||||
<zan-actionsheet v-model="show1" :actions="actions1">
|
||||
</zan-actionsheet>
|
||||
```
|
||||
:::
|
||||
|
||||
### 带取消按钮的ActionSheet
|
||||
|
||||
:::demo 带取消按钮的ActionSheet
|
||||
```html
|
||||
<div class="zan-row">
|
||||
<zan-button @click="show2 = true">弹出带取消按钮的actionsheet</zan-button>
|
||||
</div>
|
||||
<zan-actionsheet v-model="show2" :actions="actions1" cancel-text="取消">
|
||||
</zan-actionsheet>
|
||||
```
|
||||
:::
|
||||
|
||||
### 带标题的ActionSheet
|
||||
|
||||
:::demo 带标题的ActionSheet
|
||||
```html
|
||||
<div class="zan-row">
|
||||
<zan-button @click="show3 = true">弹出带标题的actionsheet</zan-button>
|
||||
</div>
|
||||
<zan-actionsheet v-model="show3" title="支持以下配送方式" class="title-actionsheet">
|
||||
<p>一些内容</p>
|
||||
</zan-actionsheet>
|
||||
```
|
||||
:::
|
||||
|
||||
点击以下按钮查看手机端效果:
|
||||
|
||||
<zan-button @click="mobileShow = true">点击查看手机端效果</zan-button>
|
||||
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| actions | 行动按钮数组 | Array | [] | |
|
||||
| title | 标题 | String | | |
|
||||
| cancelText | 取消按钮文案 | String | | |
|
||||
| overlay | 是否显示遮罩 | Boolean | | |
|
||||
| closeOnClickOverlay | 点击遮罩是否关闭ActionSheet | Boolean | | |
|
||||
|
||||
### actions
|
||||
|
||||
`API`中的`actions`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`:
|
||||
|
||||
| key | 说明 |
|
||||
|-----------|-----------|
|
||||
| name | 标题 |
|
||||
| subname | 二级标题 |
|
||||
| className | 为对应列添加特殊的`class` |
|
||||
| loading | 是否是loading状态 |
|
@ -21,15 +21,12 @@
|
||||
:::demo 高级用法
|
||||
```html
|
||||
<zan-card
|
||||
title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余"
|
||||
desc="商品SKU1,商品SKU2"
|
||||
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
|
||||
<div class="zan-card__row" slot="title">
|
||||
<h4 class="zan-card__title">商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余</h4>
|
||||
<span class="zan-card__price">¥ 2.00</span>
|
||||
</div>
|
||||
<div class="zan-card__row" slot="desc">
|
||||
<h4 class="zan-card__desc">商品sku</h4>
|
||||
<span class="zan-card__num">x 2</span>
|
||||
</div>
|
||||
<div class="zan-card__footer" slot="footer">
|
||||
|
@ -1,7 +1,20 @@
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b dialog {
|
||||
.zan-button {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { Dialog } from 'src/index';
|
||||
import MobileComputed from 'components/mobile-computed';
|
||||
|
||||
export default {
|
||||
mixins: [MobileComputed],
|
||||
|
||||
methods: {
|
||||
handleAlertClick() {
|
||||
Dialog.alert({
|
||||
@ -66,6 +79,12 @@ export default {
|
||||
```
|
||||
:::
|
||||
|
||||
点击以下按钮查看手机端效果:
|
||||
|
||||
<zan-button @click="mobileShow = true">点击查看手机端效果</zan-button>
|
||||
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
|
||||
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|
@ -1,3 +1,13 @@
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
username: 'zhangmin'
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
## Field组件
|
||||
|
||||
表单中`input`或`textarea`的输入框。
|
||||
@ -9,7 +19,7 @@
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<zan-cell-group>
|
||||
<zan-field type="text" label="用户名:" placeholder="请输入用户名"></zan-field>
|
||||
<zan-field type="text" label="用户名:" placeholder="请输入用户名" v-model="username"></zan-field>
|
||||
<zan-field type="password" label="密码:" placeholder="请输入密码"></zan-field>
|
||||
<zan-field type="textarea" label="个人介绍:" placeholder="请输入个人介绍"></zan-field>
|
||||
</zan-cell-group>
|
||||
@ -28,14 +38,26 @@
|
||||
```
|
||||
:::
|
||||
|
||||
### 监听change事件
|
||||
### 禁用的输入框
|
||||
|
||||
监听组件的`change`事件。
|
||||
传入`disabled`属性即可。
|
||||
|
||||
:::demo 监听change事件
|
||||
:::demo 禁用的输入框
|
||||
```html
|
||||
<zan-cell-group>
|
||||
<zan-field type="text" label="用户名:" placeholder="请输入用户名" @change="handleChange"></zan-field>
|
||||
<zan-field label="用户名:" type="text" placeholder="请输入用户名" v-model="username" disabled></zan-field>
|
||||
</zan-cell-group>
|
||||
```
|
||||
:::
|
||||
|
||||
### 错误的输入框
|
||||
|
||||
传入`error`属性即可。
|
||||
|
||||
:::demo 错误的输入框
|
||||
```html
|
||||
<zan-cell-group>
|
||||
<zan-field label="用户名:" type="text" placeholder="请输入用户名" error></zan-field>
|
||||
</zan-cell-group>
|
||||
```
|
||||
:::
|
||||
@ -49,6 +71,7 @@
|
||||
| value | 输入框的值 | string | '' | |
|
||||
| label | 输入框标签 | string | '' | |
|
||||
| disabled | 是否禁用输入框 | boolean | false | |
|
||||
| error | 输入框是否有错误 | boolean | false | |
|
||||
| readonly | 输入框是否只读 | boolean | false | |
|
||||
| maxlength | 输入框maxlength | [String, Number] | '' | |
|
||||
|
||||
|
43
docs/examples-docs/icon.md
Normal file
43
docs/examples-docs/icon.md
Normal file
@ -0,0 +1,43 @@
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b icon {
|
||||
|
||||
.zan-icon {
|
||||
margin: 10px;
|
||||
font-size: 45px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
## Icon
|
||||
|
||||
### 所有Icon
|
||||
|
||||
:::demo 所有Icon
|
||||
```html
|
||||
<zan-icon name="album"></zan-icon>
|
||||
<zan-icon name="arrow"></zan-icon>
|
||||
<zan-icon name="camera"></zan-icon>
|
||||
<zan-icon name="certificate"></zan-icon>
|
||||
<zan-icon name="check"></zan-icon>
|
||||
<zan-icon name="checked"></zan-icon>
|
||||
<zan-icon name="close"></zan-icon>
|
||||
<zan-icon name="gift"></zan-icon>
|
||||
<zan-icon name="home"></zan-icon>
|
||||
<zan-icon name="location"></zan-icon>
|
||||
<zan-icon name="message"></zan-icon>
|
||||
<zan-icon name="send"></zan-icon>
|
||||
<zan-icon name="shopping-cart"></zan-icon>
|
||||
<zan-icon name="sign"></zan-icon>
|
||||
<zan-icon name="store"></zan-icon>
|
||||
<zan-icon name="topay"></zan-icon>
|
||||
<zan-icon name="tosend"></zan-icon>
|
||||
```
|
||||
:::
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| name | icon名称 | string | '' | |
|
@ -5,6 +5,53 @@ const citys = {
|
||||
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
|
||||
};
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickerColumns: [
|
||||
{
|
||||
values: Object.keys(citys),
|
||||
className: 'column1'
|
||||
},
|
||||
{
|
||||
values: ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
|
||||
className: 'column2'
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
handlePickerChange(picker, values) {
|
||||
picker.setColumnValues(1, citys[values[0]]);
|
||||
},
|
||||
handlePickerCancel() {
|
||||
alert('picker cancel');
|
||||
},
|
||||
handlePickerConfirm() {
|
||||
alert('picker confirm');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
## Picker组件
|
||||
|
||||
模仿iOS中的`UIPickerView`。
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<zan-picker :columns="pickerColumns" @change="handlePickerChange"></zan-picker>
|
||||
|
||||
<script>
|
||||
const citys = {
|
||||
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
|
||||
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
|
||||
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
|
||||
};
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -28,16 +75,51 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
## Picker组件
|
||||
### 带toolbar的Picker
|
||||
|
||||
模仿iOS中的`UIPickerView`。
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
:::demo 带toolbar的Picker
|
||||
```html
|
||||
<zan-picker :columns="pickerColumns" @change="handlePickerChange"></zan-picker>
|
||||
<zan-picker :columns="pickerColumns" show-toolbar @change="handlePickerChange" @cancel="handlePickerCancel" @confirm="handlePickerConfirm"></zan-picker>
|
||||
|
||||
<script>
|
||||
const citys = {
|
||||
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
|
||||
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
|
||||
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
|
||||
};
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickerColumns: [
|
||||
{
|
||||
values: Object.keys(citys),
|
||||
className: 'column1'
|
||||
},
|
||||
{
|
||||
values: ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
|
||||
className: 'column2'
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
handlePickerChange(picker, values) {
|
||||
picker.setColumnValues(1, citys[values[0]]);
|
||||
},
|
||||
handlePickerCancel() {
|
||||
alert('picker cancel');
|
||||
},
|
||||
handlePickerConfirm() {
|
||||
alert('picker confirm');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -1,5 +1,44 @@
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b popup {
|
||||
.zan-popup-1 {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.zan-popup-2 {
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, 0.701961);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.zan-popup-3 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.zan-popup-4 {
|
||||
width: 60%;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.zan-button {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import MobileComputed from 'components/mobile-computed';
|
||||
import Dialog from 'packages/dialog';
|
||||
|
||||
export default {
|
||||
mixins: [MobileComputed],
|
||||
|
||||
data() {
|
||||
return {
|
||||
popupShow1: false,
|
||||
@ -17,6 +56,19 @@ export default {
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
showDialog() {
|
||||
Dialog.confirm({
|
||||
title: 'confirm标题',
|
||||
message: '弹窗提示文字,左右始终距离边20PX,上下距离20PX,文字左对齐。弹窗提示文字,左右始终距离边20PX,上下距离20PX,文字左对齐。'
|
||||
}).then((action) => {
|
||||
console.log(action);
|
||||
}, (error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -28,10 +80,10 @@ export default {
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<div class="zan-row">
|
||||
<zan-button @click="popupShow1 = true">从下方弹出popup</zan-button>
|
||||
<zan-button @click="popupShow1 = true;">从下方弹出popup</zan-button>
|
||||
</div>
|
||||
<zan-popup v-model="popupShow1" position="bottom" class="zan-popup-1">
|
||||
xxxx
|
||||
<zan-button @click="showDialog">弹出dialog</zan-button>
|
||||
</zan-popup>
|
||||
|
||||
<div class="zan-row">
|
||||
@ -51,8 +103,8 @@ export default {
|
||||
<div class="zan-row">
|
||||
<zan-button @click="popupShow4 = true">从中间弹出popup</zan-button>
|
||||
</div>
|
||||
<zan-popup v-model="popupShow4" transition="popup-fade" class="zan-popup-4">
|
||||
一些内容
|
||||
<zan-popup v-model="popupShow4" class="zan-popup-4">
|
||||
从中间弹出popup
|
||||
</zan-popup>
|
||||
|
||||
<script>
|
||||
@ -77,9 +129,15 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
```
|
||||
:::
|
||||
|
||||
点击以下按钮查看手机端效果:
|
||||
|
||||
<zan-button @click="mobileShow = true">点击查看手机端效果</zan-button>
|
||||
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|
72
docs/examples-docs/progress.md
Normal file
72
docs/examples-docs/progress.md
Normal file
@ -0,0 +1,72 @@
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b progress {
|
||||
@e wrapper {
|
||||
padding: 5px;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
## Switch组件
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :percentage="0"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo2" :percentage="46"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :percentage="100"></zan-progress>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### Inactive
|
||||
:::demo Inactive
|
||||
```html
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :inactive="true" :percentage="0"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo2" :inactive="true" :percentage="46"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" :inactive="true" :percentage="100"></zan-progress>
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### 自定义颜色和文字
|
||||
:::demo 自定义颜色
|
||||
```html
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" pivot-text="红色" color="#ed5050" :percentage="26"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" pivot-text="橙色" color="#f60" :percentage="46"></zan-progress>
|
||||
</div>
|
||||
<div class="demo-progress__wrapper">
|
||||
<zan-progress class="demo-progress__demo1" pivot-text="黄色" color="#f09000" :percentage="66"></zan-progress>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| inactive | 是否只会 | boolean | false | true, false |
|
||||
| percentage | 进度百分比 | number | false | 0-100 |
|
||||
| pivotText | 文字显示 | string | 百分比文字 | - |
|
||||
| color | 进度条颜色 | string | #38f | hexvalue |
|
||||
| textColor | 进度条文字颜色 | string | #fff | hexvalue |
|
||||
|
65
docs/examples-docs/quantity.md
Normal file
65
docs/examples-docs/quantity.md
Normal file
@ -0,0 +1,65 @@
|
||||
<style>
|
||||
@component-namespace demo {
|
||||
@b quantity {
|
||||
.zan-quantity {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.curr-quantity {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
quantity1: 1,
|
||||
quantity2: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
## Quantity
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<zan-quantity v-model="quantity1"></zan-quantity>
|
||||
<p class="curr-quantity">当前值:{{ quantity1 }}</p>
|
||||
```
|
||||
:::
|
||||
|
||||
### 禁用Quantity
|
||||
|
||||
:::demo 禁用Quantity
|
||||
```html
|
||||
<zan-quantity v-model="quantity1" disabled></zan-quantity>
|
||||
```
|
||||
:::
|
||||
|
||||
### 高级用法
|
||||
|
||||
默认是每次加减为1,可以对组件设置`step`、`min`、`max`、`defaultValue`属性。
|
||||
|
||||
:::demo 高级用法
|
||||
```html
|
||||
<zan-quantity v-model="quantity2" min="5" max="40" step="2" default-value="9"></zan-quantity>
|
||||
<p class="curr-quantity">当前值:{{ quantity2 }}</p>
|
||||
```
|
||||
:::
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| min | 最小值 | string/number | 1 | '' |
|
||||
| max | 最大值 | string/number | '' | '' |
|
||||
| step | 步数 | string/number | 1 | '' |
|
||||
| disabled | 是否被禁用了 | boolean | false | '' |
|
||||
| defaultValue | 默认值 | string/number | 1 | '' |
|
||||
|
126
docs/examples-docs/tab.md
Normal file
126
docs/examples-docs/tab.md
Normal file
@ -0,0 +1,126 @@
|
||||
## Tab 组件
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<zan-tabs>
|
||||
<zan-tab title="选项一">内容一</zan-tab>
|
||||
<zan-tab title="选项二">内容二</zan-tab>
|
||||
<zan-tab title="选项三">内容三</zan-tab>
|
||||
<zan-tab title="选项四">内容四</zan-tab>
|
||||
<zan-tab title="选项五">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
```
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
popalert() {
|
||||
alert('haha')
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
:::
|
||||
### 禁用用法
|
||||
:::demo 禁用用法
|
||||
```html
|
||||
<zan-tabs>
|
||||
<zan-tab title="选项一">内容一</zan-tab>
|
||||
<zan-tab disable title="选项二" @disable="popalert">内容二</zan-tab>
|
||||
<zan-tab title="选项三">内容三</zan-tab>
|
||||
<zan-tab title="选项四">内容四</zan-tab>
|
||||
<zan-tab title="选项五">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
popalert() {
|
||||
alert('haha')
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### card样式用法
|
||||
:::demo card样式用法
|
||||
```html
|
||||
<zan-tabs type="card">
|
||||
<zan-tab title="选项一">内容一</zan-tab>
|
||||
<zan-tab title="选项二">内容二</zan-tab>
|
||||
<zan-tab title="选项三">内容三</zan-tab>
|
||||
<zan-tab title="选项四">内容四</zan-tab>
|
||||
<zan-tab title="选项五">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
```
|
||||
:::
|
||||
<style>
|
||||
.page-tab {
|
||||
padding: 0 15px;
|
||||
}
|
||||
.custom-tabwrap .zan-tab-active{
|
||||
color: #20a0ff;
|
||||
}
|
||||
.custom-tabwrap .zan-tabs-nav-bar{
|
||||
background: #20a0ff;
|
||||
}
|
||||
.custom-tab {
|
||||
font-weight: bold;
|
||||
}
|
||||
.custom-pane {
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
### 自定义样式用法
|
||||
:::demo 自定义样式用法
|
||||
```html
|
||||
<zan-tabs active="2" navclass="custom-tabwrap">
|
||||
<zan-tab title="选项一" class="custom-pane">内容一</zan-tab>
|
||||
<zan-tab title="选项二" class="custom-pane">内容二</zan-tab>
|
||||
<zan-tab title="选项三" class="custom-pane">内容三</zan-tab>
|
||||
<zan-tab title="选项四" class="custom-pane">内容四</zan-tab>
|
||||
<zan-tab title="选项五" class="custom-pane">内容五</zan-tab>
|
||||
</zan-tabs>
|
||||
<style>
|
||||
.page-tab {
|
||||
padding: 0 15px;
|
||||
}
|
||||
.custom-tabwrap .zan-tab-active{
|
||||
color: #20a0ff;
|
||||
}
|
||||
.custom-tabwrap .zan-tabs-nav-bar{
|
||||
background: #20a0ff;
|
||||
}
|
||||
.custom-tab {
|
||||
font-weight: bold;
|
||||
}
|
||||
.custom-pane {
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### zan-tabs API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| classtype | 两种UI | string | line | card |
|
||||
| active | 默认激活的tab | string || number | 0 | |
|
||||
| navclass | tabs的内部nav上的自定义classname | string | '' | |
|
||||
|
||||
|
||||
### zan-tab API
|
||||
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| title | tab的标题 | string | '' | required |
|
||||
| disable | 是否禁用这个tab | Boolean | false | |
|
||||
|
@ -2,28 +2,6 @@
|
||||
|
||||
### 基础用法
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<div class="waterfall">
|
||||
<div
|
||||
v-waterfall-lower="loadMore"
|
||||
v-waterfall-upper="loadMoreUpper"
|
||||
waterfall-disabled="isWaterfallDisabled"
|
||||
waterfall-offset="400"
|
||||
>
|
||||
<div
|
||||
class="waterfall-item"
|
||||
v-for="item in list"
|
||||
style="text-align: center;"
|
||||
>
|
||||
{{ item }}
|
||||
</div>
|
||||
<div v-if="loading" style="text-align: center;">
|
||||
loading
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
@ -62,6 +40,35 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.waterfall {
|
||||
max-height: 300px;
|
||||
overflow: scroll;
|
||||
}
|
||||
</style>
|
||||
|
||||
:::demo 基础用法
|
||||
```html
|
||||
<div class="waterfall">
|
||||
<div
|
||||
v-waterfall-lower="loadMore"
|
||||
v-waterfall-upper="loadMoreUpper"
|
||||
waterfall-disabled="isWaterfallDisabled"
|
||||
waterfall-offset="400"
|
||||
>
|
||||
<div
|
||||
class="waterfall-item"
|
||||
v-for="item in list"
|
||||
style="text-align: center;"
|
||||
>
|
||||
{{ item }}
|
||||
</div>
|
||||
<div v-if="loading" style="text-align: center;">
|
||||
loading
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
@ -69,6 +76,6 @@ export default {
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| waterfall-disabled | 是否禁止瀑布流触发 | Boolean | false | |
|
||||
| waterfall-disabled | 在vue对象中表示是否禁止瀑布流触发的key值 | String | - | |
|
||||
| waterfall-offset | 触发瀑布流加载的阈值 | Number | 300 | |
|
||||
|
||||
|
@ -9,6 +9,12 @@ import ZanUI from 'src/index.js';
|
||||
|
||||
import 'packages/zanui-css/src/index.css';
|
||||
|
||||
function isMobile() {
|
||||
var platform = navigator.userAgent.toLowerCase();
|
||||
return (/(android|bb\d+|meego).+mobile|kdtunion|weibo|m2oapp|micromessenger|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i).test(platform) ||
|
||||
(/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i).test(platform.substr(0, 4));
|
||||
}
|
||||
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(ZanUI);
|
||||
Vue.component('side-nav', SideNav);
|
||||
@ -31,6 +37,10 @@ router.beforeEach((route, redirect, next) => {
|
||||
if (route.path !== '/') {
|
||||
indexScrollTop = document.body.scrollTop;
|
||||
}
|
||||
if (isMobile()) {
|
||||
window.location.replace(location.pathname + 'examples.html#' + route.path);
|
||||
return;
|
||||
}
|
||||
document.title = route.meta.title || document.title;
|
||||
next();
|
||||
});
|
||||
|
@ -27,6 +27,10 @@
|
||||
"path": "/button",
|
||||
"title": "Button"
|
||||
},
|
||||
{
|
||||
"path": "/icon",
|
||||
"title": "Icon"
|
||||
},
|
||||
{
|
||||
"path": "/cell",
|
||||
"title": "Cell"
|
||||
@ -89,6 +93,10 @@
|
||||
{
|
||||
"groupName": "JS组件",
|
||||
"list": [
|
||||
{
|
||||
"path": "/actionsheet",
|
||||
"title": "ActionSheet"
|
||||
},
|
||||
{
|
||||
"path": "/tab",
|
||||
"title": "Tab"
|
||||
@ -125,6 +133,10 @@
|
||||
"path": "/swipe",
|
||||
"title": "Swipe"
|
||||
},
|
||||
{
|
||||
"path": "/quantity",
|
||||
"title": "Quantity"
|
||||
},
|
||||
{
|
||||
"path": "/waterfall",
|
||||
"title": "Waterfall"
|
||||
|
13
package.json
13
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@youzan/zanui-vue",
|
||||
"version": "0.0.15",
|
||||
"version": "0.0.30",
|
||||
"description": "有赞vue wap组件库",
|
||||
"main": "lib/zanui.js",
|
||||
"style": "lib/zanui-css/index.css",
|
||||
@ -24,7 +24,8 @@
|
||||
"lint": "eslint src/**/*.js packages/**/*.{js,vue} --quiet",
|
||||
"test": "karma start test/unit/karma.conf.js --single-run; npm run coverage",
|
||||
"test:watch": "karma start test/unit/karma.conf.js",
|
||||
"coverage": "find test/unit/coverage/lcov-report -name 'index.html' | sed -n 1,1p | xargs -I {} open {} "
|
||||
"coverage": "find test/unit/coverage/lcov-report -name 'index.html' | sed -n 1,1p | xargs -I {} open {} ",
|
||||
"deploy": "sh build/release.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -41,7 +42,7 @@
|
||||
"raf.js": "0.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^2.1.8"
|
||||
"vue": "2.1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"2webpack2": "^1.2.1",
|
||||
@ -129,14 +130,14 @@
|
||||
"transliteration": "^1.1.11",
|
||||
"uppercamelcase": "^1.1.0",
|
||||
"url-loader": "^0.5.7",
|
||||
"vue": "^2.1.8",
|
||||
"vue": "2.1.8",
|
||||
"vue-hot-reload-api": "^1.3.3",
|
||||
"vue-html-loader": "^1.2.3",
|
||||
"vue-loader": "^10.0.2",
|
||||
"vue-loader": "^10.3.0",
|
||||
"vue-markdown-loader": "^0.6.1",
|
||||
"vue-router": "^2.0.0",
|
||||
"vue-style-loader": "^1.0.0",
|
||||
"vue-template-compiler": "^2.1.8",
|
||||
"vue-template-compiler": "2.1.8",
|
||||
"vue-template-es2015-compiler": "^1.4.2",
|
||||
"webpack": "^2.2.1",
|
||||
"webpack-dev-server": "^1.16.0",
|
||||
|
@ -1,28 +1,54 @@
|
||||
<template>
|
||||
<transition name="actionsheet-float">
|
||||
<div class="zan-actionsheet" v-show="currentValue">
|
||||
<div class="zan-actionsheet-header" v-if="title">
|
||||
<div class="zan-actionsheet" :class="[ title ? 'zan-actionsheet--withtitle' : '' ]" v-show="currentValue">
|
||||
<div class="zan-actionsheet__header" v-if="title">
|
||||
<h3 v-text="title"></h3>
|
||||
<zan-icon name="close" @click.stop="currentValue = false"></zan-icon>
|
||||
</div>
|
||||
<slot>
|
||||
<ul class="zan-actionsheet-list">
|
||||
<li v-for="item in actions" class="zan-actionsheet-item" :class="item.className" @click.stop="handleItemClick(item)">{{ item.name }}</li>
|
||||
<template v-if="!title">
|
||||
<ul class="zan-actionsheet__list">
|
||||
<li
|
||||
v-for="item in actions"
|
||||
class="zan-actionsheet__item"
|
||||
:class="[item.className, item.loading ? 'zan-actionsheet__item--loading' : '']"
|
||||
@click.stop="handleItemClick(item)">
|
||||
<template v-if="!item.loading">
|
||||
<span class="zan-actionsheet__name">{{ item.name }}</span>
|
||||
<span class="zan-actionsheet__subname" v-if="item.subname">{{ item.subname }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<zan-loading class="zan-actionsheet__loading" type="circle" color="black"></zan-loading>
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="zan-actionsheet-button" @click.stop="currentValue = false" v-if="cancelText">{{ cancelText }}</a>
|
||||
</slot>
|
||||
<a class="zan-actionsheet__button" @click.stop="currentValue = false" v-if="cancelText">{{ cancelText }}</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="zan-actionsheet__content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Popup from 'src/mixins/popup';
|
||||
import ZanLoading from 'packages/loading';
|
||||
import ZanIcon from 'packages/icon';
|
||||
|
||||
export default {
|
||||
name: 'zan-actionsheet',
|
||||
|
||||
mixins: [Popup],
|
||||
|
||||
components: {
|
||||
ZanLoading,
|
||||
ZanIcon
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {},
|
||||
actions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
@ -40,7 +66,7 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
currentValue: false
|
||||
currentValue: this.value
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<h4 v-text="title" class="zan-card__title"></h4>
|
||||
</slot>
|
||||
<slot name="desc">
|
||||
<p v-if="desc" v-text="desc" class="zan-card__title"></p>
|
||||
<p v-if="desc" v-text="desc" class="zan-card__desc"></p>
|
||||
</slot>
|
||||
<slot name="tags"></slot>
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@
|
||||
}">
|
||||
<span class="zan-checkbox__input">
|
||||
<input
|
||||
ref="input"
|
||||
v-model="currentValue"
|
||||
type="checkbox"
|
||||
class="zan-checkbox__control"
|
||||
@ -16,7 +17,7 @@
|
||||
}">
|
||||
</span>
|
||||
</span>
|
||||
<span class="zan-checkbox__label">
|
||||
<span class="zan-checkbox__label" @click="handleLabelClick">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</div>
|
||||
@ -92,6 +93,15 @@ export default {
|
||||
? this.parentGroup.disabled || this.disabled
|
||||
: this.disabled;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleLabelClick() {
|
||||
if (this.isDisabled) {
|
||||
return;
|
||||
}
|
||||
this.currentValue = !this.currentValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -3,14 +3,15 @@
|
||||
class="zan-field"
|
||||
:title="label"
|
||||
:class="{
|
||||
'is-textarea': type === 'textarea',
|
||||
'is-nolabel': !label
|
||||
'zan-field--hastextarea': type === 'textarea',
|
||||
'zan-field--nolabel': !label,
|
||||
'zan-field--disabled': disabled,
|
||||
'zan-field--error': error
|
||||
}">
|
||||
<textarea
|
||||
v-if="type === 'textarea'"
|
||||
class="zan-field__control"
|
||||
v-model="currentValue"
|
||||
@change="$emit('change', currentValue)"
|
||||
:placeholder="placeholder"
|
||||
:maxlength="maxlength"
|
||||
:disabled="disabled"
|
||||
@ -20,7 +21,6 @@
|
||||
v-else
|
||||
class="zan-field__control"
|
||||
:value="currentValue"
|
||||
@change="$emit('change', currentValue)"
|
||||
@input="handleInput"
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
@ -46,9 +46,10 @@ export default {
|
||||
default: 'text'
|
||||
},
|
||||
placeholder: String,
|
||||
value: String,
|
||||
value: {},
|
||||
label: String,
|
||||
disabled: Boolean,
|
||||
error: Boolean,
|
||||
readonly: Boolean,
|
||||
maxlength: [String, Number]
|
||||
},
|
||||
@ -66,7 +67,6 @@ export default {
|
||||
|
||||
currentValue(val) {
|
||||
this.$emit('input', val);
|
||||
console.log(val);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<i class="zanui-icon" :class="'zan-icon-' + name"></i>
|
||||
<i class="zan-icon" :class="'zan-icon-' + name" @click="handleIconClick"></i>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -8,6 +8,12 @@
|
||||
|
||||
props: {
|
||||
name: String
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleIconClick(event) {
|
||||
this.$emit('click', event);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
8
packages/lazyload/CHANGELOG.md
Normal file
8
packages/lazyload/CHANGELOG.md
Normal file
@ -0,0 +1,8 @@
|
||||
## 0.0.2 (2017-01-20)
|
||||
|
||||
* 改了bug A
|
||||
* 加了功能B
|
||||
|
||||
## 0.0.1 (2017-01-10)
|
||||
|
||||
* 第一版
|
26
packages/lazyload/README.md
Normal file
26
packages/lazyload/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# @youzan/<%= name %>
|
||||
|
||||
!!! 请在此处填写你的文档最简单描述 !!!
|
||||
|
||||
[![version][version-image]][download-url]
|
||||
[![download][download-image]][download-url]
|
||||
|
||||
[version-image]: http://npm.qima-inc.com/badge/v/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-image]: http://npm.qima-inc.com/badge/d/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-url]: http://npm.qima-inc.com/package/@youzan/<%= name %>
|
||||
|
||||
## Demo
|
||||
|
||||
## Usage
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| className | 自定义额外类名 | string | '' | '' |
|
||||
|
||||
|
||||
|
||||
|
||||
## License
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
79
packages/lazyload/index.js
Normal file
79
packages/lazyload/index.js
Normal file
@ -0,0 +1,79 @@
|
||||
export default {
|
||||
install: function(Vue, options) {
|
||||
options = options || { fade: false, nohori: false };
|
||||
// scroll结束的时候触发scrollend事件
|
||||
var timer = null;
|
||||
var topValue = 0;
|
||||
var bodyEle = document.body;
|
||||
var scrollEnd = document.createEvent('HTMLEvents');
|
||||
scrollEnd.initEvent('scrollEnd', true, false);
|
||||
function enterFrame() {
|
||||
if (bodyEle.scrollTop === topValue) {
|
||||
window.cancelAnimationFrame(timer);
|
||||
window.dispatchEvent(scrollEnd);
|
||||
} else {
|
||||
topValue = bodyEle.scrollTop;
|
||||
}
|
||||
window.requestAnimationFrame(enterFrame);
|
||||
}
|
||||
document.addEventListener('scroll', function() {
|
||||
if (!timer) {
|
||||
timer = window.requestAnimationFrame(enterFrame);
|
||||
}
|
||||
}, true);
|
||||
// vue指令
|
||||
function update(value) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
var isFadeIn = this.modifiers.fade || options.fade;
|
||||
var isNoHori = this.modifiers.nohori || options.nohori;
|
||||
// 用css3来控制过渡效果
|
||||
if (isFadeIn) {
|
||||
this.el.style.opacity = 0;
|
||||
this.el.style.transition = 'opacity .3s';
|
||||
this.el.style.webkitTransition = 'opacity .3s';
|
||||
}
|
||||
var compute = function() {
|
||||
if (this.el === null) {
|
||||
return;
|
||||
}
|
||||
var rect = this.el.getBoundingClientRect();
|
||||
var vpWidth = document.head.parentNode.clientWidth;
|
||||
var vpHeight = document.head.parentNode.clientHeight;
|
||||
var loadImg = function() {
|
||||
this.el.src = value;
|
||||
this.el.addEventListener('load', onloadEnd);
|
||||
window.removeEventListener('scrollEnd', compute, true);
|
||||
window.removeEventListener('resize', compute, true);
|
||||
}.bind(this);
|
||||
if (this.el.src === value) return;
|
||||
if (isNoHori) {
|
||||
if (rect.bottom >= 0 && rect.top <= vpHeight) {
|
||||
loadImg();
|
||||
}
|
||||
} else if (rect.bottom >= 0 && rect.top <= vpHeight && rect.right >= 0 && rect.left <= vpWidth) {
|
||||
loadImg();
|
||||
}
|
||||
}.bind(this);
|
||||
var onload = function() {
|
||||
compute();
|
||||
this.el && this.el.removeEventListener('load', onload);
|
||||
window.addEventListener('scrollEnd', compute, true);
|
||||
window.addEventListener('resize', compute, true);
|
||||
}.bind(this);
|
||||
var onloadEnd = function() {
|
||||
if (this.el === null) {
|
||||
return;
|
||||
}
|
||||
if (isFadeIn) {
|
||||
this.el.style.opacity = 1;
|
||||
}
|
||||
this.el.removeEventListener('load', onloadEnd);
|
||||
}.bind(this);
|
||||
// 元素load触发事件
|
||||
this.el.addEventListener('load', onload);
|
||||
}
|
||||
Vue.directive('lazyload', update);
|
||||
}
|
||||
};
|
10
packages/lazyload/package.json
Normal file
10
packages/lazyload/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "<%= name %>",
|
||||
"version": "<%= version %>",
|
||||
"description": "<%= description %>",
|
||||
"main": "./lib/index.js",
|
||||
"author": "<%= author %>",
|
||||
"license": "<%= license %>",
|
||||
"devDependencies": {},
|
||||
"dependencies": {}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
class="zan-picker-column__item"
|
||||
:class="{ 'zan-picker-column__item--selected': item === currentValue }"
|
||||
:style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }">
|
||||
{{item}}
|
||||
{{ typeof item === 'object' && item[valueKey] ? item[valueKey] : item }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -52,7 +52,8 @@ export default {
|
||||
type: Number,
|
||||
default: DEFAULT_ITEM_HEIGHT
|
||||
},
|
||||
value: {}
|
||||
value: {},
|
||||
valueKey: String
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<div class="zan-picker">
|
||||
<div class="zan-picker__toolbar">
|
||||
<div class="zan-picker__toolbar" v-show="showToolbar">
|
||||
<slot>
|
||||
<a href="javascript:void(0)" class="zan-picker__cancel" @click="handlePickerCancel">取消</a>
|
||||
<a href="javascript:void(0)" class="zan-picker__confirm" @click="handlePickerConfirm">完成</a>
|
||||
</slot>
|
||||
</div>
|
||||
<div class="zan-picker__columns" :class="['zan-picker__columns--' + columns.length]">
|
||||
@ -12,7 +14,8 @@
|
||||
:class-name="item.className"
|
||||
:itemHeight="itemHeight"
|
||||
:visible-item-count="visibleItemCount"
|
||||
@change="columnValueChange">
|
||||
:value-key="valueKey"
|
||||
@change="columnValueChange(index)">
|
||||
</picker-column>
|
||||
<div class="zan-picker-center-highlight" :style="{ height: itemHeight + 'px', marginTop: -itemHeight / 2 + 'px' }"></div>
|
||||
</div>
|
||||
@ -60,8 +63,9 @@ export default {
|
||||
*/
|
||||
showToolbar: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
default: false
|
||||
},
|
||||
valueKey: String
|
||||
},
|
||||
|
||||
computed: {
|
||||
@ -78,11 +82,17 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
handlePickerCancel() {
|
||||
this.$emit('cancel', this.values);
|
||||
},
|
||||
handlePickerConfirm() {
|
||||
this.$emit('confirm', this.values);
|
||||
},
|
||||
/**
|
||||
* 处理列`change`事件
|
||||
*/
|
||||
columnValueChange() {
|
||||
this.$emit('change', this, this.values);
|
||||
columnValueChange(index) {
|
||||
this.$emit('change', this, this.values, index);
|
||||
},
|
||||
|
||||
/**
|
||||
|
26
packages/progress/README.md
Normal file
26
packages/progress/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# @youzan/<%= name %>
|
||||
|
||||
!!! 请在此处填写你的文档最简单描述 !!!
|
||||
|
||||
[![version][version-image]][download-url]
|
||||
[![download][download-image]][download-url]
|
||||
|
||||
[version-image]: http://npm.qima-inc.com/badge/v/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-image]: http://npm.qima-inc.com/badge/d/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-url]: http://npm.qima-inc.com/package/@youzan/<%= name %>
|
||||
|
||||
## Demo
|
||||
|
||||
## Usage
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| className | 自定义额外类名 | string | '' | '' |
|
||||
|
||||
|
||||
|
||||
|
||||
## License
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
3
packages/progress/index.js
Normal file
3
packages/progress/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Progress from './src/progress';
|
||||
|
||||
export default Progress;
|
10
packages/progress/package.json
Normal file
10
packages/progress/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@youzan/zan-progress",
|
||||
"version": "0.0.1",
|
||||
"description": "progress component",
|
||||
"main": "./index.js",
|
||||
"author": "jiangruowei",
|
||||
"license": "MIT",
|
||||
"devDependencies": {},
|
||||
"dependencies": {}
|
||||
}
|
84
packages/progress/src/progress.vue
Normal file
84
packages/progress/src/progress.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div class="zan-progress">
|
||||
<div class="zan-progress__bar">
|
||||
<span class="zan-progress__bar__finished-portion" :style="{backgroundColor: componentColor, width: percentage + '%'}"></span>
|
||||
<span class="zan-progress__bar__pivot" :style="pivotStyle">
|
||||
{{pivotText}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* zan-progress
|
||||
* @module components/progress
|
||||
* @desc 开关
|
||||
* @param {boolean} [inactive=false] - 是否置灰
|
||||
* @param {number} [percentage=0] - 进度百分比
|
||||
* @param {string} [pivotText=percentage] - 进度条显示文字
|
||||
* @param {string} [color='#38f'] - 进度条颜色
|
||||
* @param {string} [textColor='#fff'] - 进度条文字颜色
|
||||
*
|
||||
* @example
|
||||
* <zan-switch checked="true" disabled="false"></zan-switch>
|
||||
*/
|
||||
export default {
|
||||
name: 'zan-progress',
|
||||
|
||||
props: {
|
||||
percentage: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
validate(value) {
|
||||
return value <= 100 && value >= 0;
|
||||
}
|
||||
},
|
||||
inactive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pivotText: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return this.percentage.toString() + '%';
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#38f'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
componentColor() {
|
||||
return this.inactive ? '#cacaca' : this.color;
|
||||
},
|
||||
pivotStyle() {
|
||||
const pivotStyle = {
|
||||
backgroundColor: this.componentColor,
|
||||
color: this.textColor,
|
||||
left: this.percentage + '%',
|
||||
marginLeft: '-14px'
|
||||
};
|
||||
console.log(this.percentage);
|
||||
if (this.percentage <= 5) {
|
||||
pivotStyle.left = '0%';
|
||||
pivotStyle.marginLeft = '0';
|
||||
} else if (this.percentage >= 95) {
|
||||
pivotStyle.left = '100%';
|
||||
pivotStyle.marginLeft = '-28px';
|
||||
} else {
|
||||
pivotStyle.left = this.percentage + '%';
|
||||
pivotStyle.marginLeft = '-14px';
|
||||
}
|
||||
|
||||
return pivotStyle;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
8
packages/quantity/CHANGELOG.md
Normal file
8
packages/quantity/CHANGELOG.md
Normal file
@ -0,0 +1,8 @@
|
||||
## 0.0.2 (2017-01-20)
|
||||
|
||||
* 改了bug A
|
||||
* 加了功能B
|
||||
|
||||
## 0.0.1 (2017-01-10)
|
||||
|
||||
* 第一版
|
26
packages/quantity/README.md
Normal file
26
packages/quantity/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# @youzan/<%= name %>
|
||||
|
||||
!!! 请在此处填写你的文档最简单描述 !!!
|
||||
|
||||
[![version][version-image]][download-url]
|
||||
[![download][download-image]][download-url]
|
||||
|
||||
[version-image]: http://npm.qima-inc.com/badge/v/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-image]: http://npm.qima-inc.com/badge/d/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-url]: http://npm.qima-inc.com/package/@youzan/<%= name %>
|
||||
|
||||
## Demo
|
||||
|
||||
## Usage
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| className | 自定义额外类名 | string | '' | '' |
|
||||
|
||||
|
||||
|
||||
|
||||
## License
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
3
packages/quantity/index.js
Normal file
3
packages/quantity/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Quantity from './src/quantity';
|
||||
|
||||
export default Quantity;
|
10
packages/quantity/package.json
Normal file
10
packages/quantity/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "<%= name %>",
|
||||
"version": "<%= version %>",
|
||||
"description": "<%= description %>",
|
||||
"main": "./lib/index.js",
|
||||
"author": "<%= author %>",
|
||||
"license": "<%= license %>",
|
||||
"devDependencies": {},
|
||||
"dependencies": {}
|
||||
}
|
104
packages/quantity/src/quantity.vue
Normal file
104
packages/quantity/src/quantity.vue
Normal file
@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div class="zan-quantity">
|
||||
<button
|
||||
@click="handleChange('minus')"
|
||||
class="zan-quantity__stepper zan-quantity__minus"
|
||||
:class="{
|
||||
'zan-quantity__minus--disabled': isMinusDisabled
|
||||
}">
|
||||
</button>
|
||||
<input type="text" class="zan-quantity__input" :value="currentValue" @input="handleInputChange" :disabled="disabled">
|
||||
<button
|
||||
@click="handleChange('plus')"
|
||||
class="zan-quantity__stepper zan-quantity__plus"
|
||||
:class="{
|
||||
'zan-quantity__plus--disabled': isPlusDisabled
|
||||
}">
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'zan-quantity',
|
||||
|
||||
props: {
|
||||
min: {
|
||||
type: [String, Number],
|
||||
default: 1
|
||||
},
|
||||
max: {
|
||||
type: [String, Number],
|
||||
default: Infinity
|
||||
},
|
||||
value: {},
|
||||
step: {
|
||||
type: [String, Number],
|
||||
default: 1
|
||||
},
|
||||
disabled: Boolean,
|
||||
defaultValue: {
|
||||
type: [String, Number],
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value ? +this.value : +this.defaultValue
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
isMinusDisabled() {
|
||||
const min = +this.min;
|
||||
const step = +this.step;
|
||||
const currentValue = +this.currentValue;
|
||||
return min === currentValue || (currentValue - step) < min || this.disabled;
|
||||
},
|
||||
isPlusDisabled() {
|
||||
const max = +this.max;
|
||||
const step = +this.step;
|
||||
const currentValue = +this.currentValue;
|
||||
return max === currentValue || (currentValue + step) > max || this.disabled;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentValue(val) {
|
||||
this.$emit('input', +val);
|
||||
},
|
||||
value(val) {
|
||||
if (val) {
|
||||
this.currentValue = +val;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleInputChange(event) {
|
||||
let val = +event.target.value;
|
||||
const max = +this.max;
|
||||
const min = +this.min;
|
||||
|
||||
if (val > max) {
|
||||
val = max;
|
||||
} else if (val < min) {
|
||||
val = min;
|
||||
}
|
||||
|
||||
this.currentValue = val;
|
||||
},
|
||||
handleChange(type) {
|
||||
if ((this.isMinusDisabled && type === 'minus') || (this.isPlusDisabled && type === 'plus')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const step = +this.step;
|
||||
const currentValue = +this.currentValue;
|
||||
this.currentValue = type === 'minus' ? (currentValue - step) : (currentValue + step);
|
||||
this.$emit('change', this.currentValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
8
packages/tab/CHANGELOG.md
Normal file
8
packages/tab/CHANGELOG.md
Normal file
@ -0,0 +1,8 @@
|
||||
## 0.0.2 (2017-01-20)
|
||||
|
||||
* 改了bug A
|
||||
* 加了功能B
|
||||
|
||||
## 0.0.1 (2017-01-10)
|
||||
|
||||
* 第一版
|
26
packages/tab/README.md
Normal file
26
packages/tab/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# @youzan/<%= name %>
|
||||
|
||||
!!! 请在此处填写你的文档最简单描述 !!!
|
||||
|
||||
[![version][version-image]][download-url]
|
||||
[![download][download-image]][download-url]
|
||||
|
||||
[version-image]: http://npm.qima-inc.com/badge/v/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-image]: http://npm.qima-inc.com/badge/d/@youzan/<%= name %>.svg?style=flat-square
|
||||
[download-url]: http://npm.qima-inc.com/package/@youzan/<%= name %>
|
||||
|
||||
## Demo
|
||||
|
||||
## Usage
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| className | 自定义额外类名 | string | '' | '' |
|
||||
|
||||
|
||||
|
||||
|
||||
## License
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
2
packages/tab/index.js
Normal file
2
packages/tab/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
import Tab from './src/tab';
|
||||
export default Tab;
|
10
packages/tab/package.json
Normal file
10
packages/tab/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "<%= name %>",
|
||||
"version": "<%= version %>",
|
||||
"description": "<%= description %>",
|
||||
"main": "./lib/index.js",
|
||||
"author": "<%= author %>",
|
||||
"license": "<%= license %>",
|
||||
"devDependencies": {},
|
||||
"dependencies": {}
|
||||
}
|
27
packages/tab/src/tab.vue
Normal file
27
packages/tab/src/tab.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="zan-tabs-pane" :class="classNames">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'zan-tab',
|
||||
props: {
|
||||
// 选项卡头显示文字
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
disable: Boolean
|
||||
},
|
||||
computed: {
|
||||
classNames() {
|
||||
return { 'is-select': this.$parent.tabs.indexOf(this) === this.$parent.switchActiveTabKey };
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$parent.tabs.push(this);
|
||||
}
|
||||
};
|
||||
</script>
|
79
packages/tab/src/tabs.vue
Normal file
79
packages/tab/src/tabs.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="zan-tabs">
|
||||
<div class="zan-tabs-nav" :class="classNames">
|
||||
<div class="zan-tabs-nav-bar" :style="navBarStyle"></div>
|
||||
<div
|
||||
v-for="(tab, index) in tabs"
|
||||
class="zan-tab"
|
||||
:class="{'zan-tab-active': index == switchActiveTabKey}"
|
||||
ref="tabkey"
|
||||
@click="handleTabClick(index,tab)"
|
||||
>
|
||||
{{ tab.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="zan-tabs-content"><slot></slot></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'zan-tabs',
|
||||
props: {
|
||||
// 外部传入的激活的tab标签
|
||||
active: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
// 是默认的line还是card
|
||||
type: {
|
||||
type: String,
|
||||
default: 'line'
|
||||
},
|
||||
// nav的wrap的样式
|
||||
navclass: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabs: [],
|
||||
isReady: false,
|
||||
switchActiveTabKey: this.active
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classNames() {
|
||||
return [`zan-tabs-${this.type}`, this.navclass];
|
||||
},
|
||||
navBarStyle() {
|
||||
if (!this.isReady) return;
|
||||
const tabKey = this.switchActiveTabKey;
|
||||
const elem = this.$refs.tabkey[tabKey];
|
||||
const offsetWidth = `${elem.offsetWidth || 0}px`;
|
||||
const offsetLeft = `${elem.offsetLeft || 0}px`;
|
||||
return {
|
||||
width: offsetWidth,
|
||||
transform: `translate3d(${offsetLeft}, 0px, 0px)`
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTabClick(index, el) {
|
||||
if (el.disable) {
|
||||
el.$emit('disable');
|
||||
return;
|
||||
}
|
||||
this.switchActiveTabKey = index;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 页面载入完成
|
||||
this.$nextTick(() => {
|
||||
// 可以开始触发在computed中关于nav-bar的css动画
|
||||
this.isReady = true;
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
3
packages/tabs/index.js
Normal file
3
packages/tabs/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Tabs from '../tab/src/tabs';
|
||||
|
||||
export default Tabs;
|
@ -14,6 +14,7 @@ function doBindEvent() {
|
||||
if (disabledExpr) {
|
||||
this.vm.$watch(disabledExpr, (value) => {
|
||||
this.disabled = value;
|
||||
this.scrollEventListener();
|
||||
});
|
||||
disabled = Boolean(this.vm[disabledExpr]);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@youzan/zanui-css",
|
||||
"version": "0.0.15",
|
||||
"version": "0.0.30",
|
||||
"description": "zanui css.",
|
||||
"main": "lib/index.css",
|
||||
"style": "lib/index.css",
|
||||
|
@ -1,9 +1,81 @@
|
||||
@import './common/var.css';
|
||||
@import './mixins/border_retina.css';
|
||||
|
||||
@component-namespace zan {
|
||||
@b actionsheet {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
right: auto;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
transition: .2s ease-out;
|
||||
background-color: #e0e0e0;
|
||||
|
||||
@m withtitle {
|
||||
background-color: $c-white;
|
||||
}
|
||||
|
||||
@e item {
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
color: $c-black;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
background-color: $c-white;
|
||||
|
||||
@m loading {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
@mixin border-retina (top);
|
||||
}
|
||||
}
|
||||
|
||||
@e subname {
|
||||
color: $c-gray-darker;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@e loading {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@e button {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
line-height: 50px;
|
||||
color: $c-black;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
background-color: $c-white;
|
||||
}
|
||||
|
||||
@e header {
|
||||
line-height: 44px;
|
||||
color: $c-black;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
@mixin border-retina (top, bottom);
|
||||
}
|
||||
|
||||
.zan-icon-close {
|
||||
position: absolute;
|
||||
font-size: 22px;
|
||||
line-height: 22px;
|
||||
top: 11px;
|
||||
right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actionsheet-float-bottom-enter,
|
||||
.actionsheet-float-bottom-leave-active {
|
||||
.actionsheet-float-enter,
|
||||
.actionsheet-float-leave-active {
|
||||
transform: translate3d(-50%, 100%, 0);
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
@component-namespace zan {
|
||||
@b card {
|
||||
padding: 5px 15px;
|
||||
padding: 5px 15px 5px 115px;
|
||||
height: 90px;
|
||||
background: #FAFAFA;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
@ -13,15 +14,17 @@
|
||||
}
|
||||
|
||||
@e img {
|
||||
float: left;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
border: 0;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
@e content {
|
||||
margin-left: 100px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
|
||||
@when center {
|
||||
display: table;
|
||||
@ -45,6 +48,7 @@
|
||||
color: #333;
|
||||
max-height: 40px;
|
||||
margin-bottom: 5px;
|
||||
word-break: break-all;
|
||||
@mixin multi-ellipsis 2;
|
||||
}
|
||||
|
||||
@ -52,6 +56,7 @@
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
max-height: 20px;
|
||||
word-break: break-all;
|
||||
@mixin multi-ellipsis 1;
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,13 @@
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
@when textarea {
|
||||
@m hastextarea {
|
||||
.zan-field__control {
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@when nolabel {
|
||||
@m nolabel {
|
||||
.zan-cell__title {
|
||||
display: none;
|
||||
}
|
||||
@ -23,6 +23,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
@m disabled {
|
||||
.zan-field__control {
|
||||
color: $c-gray-dark;
|
||||
}
|
||||
}
|
||||
|
||||
@m error {
|
||||
.zan-field__control,
|
||||
.zan-cell__title {
|
||||
color: $c-red;
|
||||
}
|
||||
}
|
||||
|
||||
.zan-cell__title,
|
||||
.zan-cell__value {
|
||||
float: none;
|
||||
|
@ -18,7 +18,10 @@
|
||||
@import './steps.css';
|
||||
@import './tag.css';
|
||||
@import './checkbox.css';
|
||||
@import './tab.css';
|
||||
@import './col.css';
|
||||
@import './row.css';
|
||||
@import './image_preview.css';
|
||||
@import './actionsheet.css';
|
||||
@import './quantity.css';
|
||||
@import './progress.css';
|
||||
|
@ -1,9 +1,29 @@
|
||||
@import "./mixins/border_retina.css";
|
||||
|
||||
@component-namespace zan {
|
||||
@b picker {
|
||||
overflow: hidden;
|
||||
|
||||
@e toolbar {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
overflow: hidden;
|
||||
padding: 0 15px;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
@mixin border-retina (top, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@e cancel {
|
||||
color: #3388FF;
|
||||
float: left;
|
||||
}
|
||||
|
||||
@e confirm {
|
||||
color: #3388FF;
|
||||
float: right;
|
||||
}
|
||||
|
||||
@e columns {
|
||||
|
@ -6,6 +6,7 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.701961);
|
||||
transition: background-color .5s ease-out;
|
||||
}
|
||||
|
||||
@b popup {
|
||||
@ -18,6 +19,7 @@
|
||||
transition: .2s ease-out;
|
||||
|
||||
@m top {
|
||||
width: 100%;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
@ -34,6 +36,7 @@
|
||||
}
|
||||
|
||||
@m bottom {
|
||||
width: 100%;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
right: auto;
|
||||
|
33
packages/zanui-css/src/progress.css
Normal file
33
packages/zanui-css/src/progress.css
Normal file
@ -0,0 +1,33 @@
|
||||
@import './common/var.css';
|
||||
|
||||
@component-namespace zan {
|
||||
@b progress {
|
||||
@e bar {
|
||||
height: 4px;
|
||||
border-radius: 4.5px;
|
||||
width: 100%;
|
||||
background: $c-gray-light;
|
||||
position: relative;
|
||||
|
||||
@e finished-portion {
|
||||
border-radius: 4.5px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
@e pivot {
|
||||
padding: 2px 0;
|
||||
font-size: 8px;
|
||||
position: absolute;
|
||||
border-radius: 6px;
|
||||
width: 28px;
|
||||
background-color: $c-gray-light;
|
||||
line-height: 8px;
|
||||
text-align: center;
|
||||
top: 50%;
|
||||
transform: translate3d(0, -50%, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
packages/zanui-css/src/quantity.css
Normal file
77
packages/zanui-css/src/quantity.css
Normal file
@ -0,0 +1,77 @@
|
||||
@import './common/var.css';
|
||||
|
||||
@component-namespace zan {
|
||||
@b quantity {
|
||||
font-size: 0;
|
||||
|
||||
@e stepper {
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
box-sizing: border-box;
|
||||
background-color: $c-white;
|
||||
border: 1px solid $c-gray-dark;
|
||||
position: relative;
|
||||
outline: 0;
|
||||
padding: 5px;
|
||||
vertical-align: middle;
|
||||
|
||||
&::before {
|
||||
width: 9px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
width: 1px;
|
||||
height: 9px;
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #6c6c6c;
|
||||
}
|
||||
}
|
||||
|
||||
@e minus {
|
||||
border-radius: 2px 0 0 2px;
|
||||
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@m disabled {
|
||||
background-color: #f8f8f8;
|
||||
border-color: #e8e8e8 #999 #e8e8e8 #e8e8e8;
|
||||
}
|
||||
}
|
||||
|
||||
@e plus {
|
||||
border-radius: 0 2px 2px 0;
|
||||
|
||||
@m disabled {
|
||||
background-color: #f8f8f8;
|
||||
border-color: #e8e8e8 #e8e8e8 #e8e8e8 #999;
|
||||
}
|
||||
}
|
||||
|
||||
@e input {
|
||||
width: 33px;
|
||||
height: 26px;
|
||||
padding: 1px;
|
||||
border: 1px solid $c-gray-dark;
|
||||
border-width: 1px 0;
|
||||
box-sizing: content-box;
|
||||
color: $c-gray-darker;
|
||||
font-size: 14px;
|
||||
outline: 0;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
@ -106,7 +106,7 @@
|
||||
|
||||
.zan-step__circle-container {
|
||||
left: auto;
|
||||
right: -8px;
|
||||
right: -9px;
|
||||
}
|
||||
|
||||
.zan-step__line {
|
||||
|
100
packages/zanui-css/src/tab.css
Normal file
100
packages/zanui-css/src/tab.css
Normal file
@ -0,0 +1,100 @@
|
||||
@import "./common/var.css";
|
||||
@import "./mixins/border_retina.css";
|
||||
@component-namespace zan {
|
||||
@b tabs {
|
||||
position: relative;
|
||||
}
|
||||
@b tabs-line {
|
||||
height: 44px;
|
||||
background-color: $c-white;
|
||||
&::after {
|
||||
@mixin border-retina (top);
|
||||
@mixin border-retina (bottom);
|
||||
}
|
||||
@b tabs-nav-bar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@b tabs-card {
|
||||
height: 28px;
|
||||
margin: 0 15px;
|
||||
background-color: $c-white;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #666666;
|
||||
overflow: hidden;
|
||||
.zan-tabs-nav-bar {
|
||||
display: none;
|
||||
}
|
||||
.zan-tab {
|
||||
color: #666666;
|
||||
line-height: 28px;
|
||||
border-right: 1px solid #666666;
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
&.zan-tab-active {
|
||||
background-color: #666666;
|
||||
color: $c-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
@b tabs-nav {
|
||||
display: flex;
|
||||
transition: transform .5s cubic-bezier(.645, .045, .355, 1);
|
||||
position: relative;
|
||||
/*float: left*/
|
||||
&::after, &::before {
|
||||
display: table;
|
||||
content: " "
|
||||
}
|
||||
&::after {
|
||||
clear: both
|
||||
}
|
||||
}
|
||||
@b tabs-nav-bar {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
background-color: #f13e3a;
|
||||
transition: transform .3s cubic-bezier(.645, .045, .355, 1);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
@b tab {
|
||||
color: $c-black;
|
||||
font-size: 14px;
|
||||
line-height: 44px;
|
||||
flex: 1;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
transition: color .3s cubic-bezier(.645, .045, .355, 1);
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
@b tab-active {
|
||||
color: #FF4444;
|
||||
}
|
||||
@b tabs-pane {
|
||||
display: none;
|
||||
@when select {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
18
src/index.js
18
src/index.js
@ -21,10 +21,15 @@ import BadgeGroup from '../packages/badge-group/index.js';
|
||||
import Badge from '../packages/badge/index.js';
|
||||
import Search from '../packages/search/index.js';
|
||||
import Step from '../packages/step/index.js';
|
||||
import Tabs from '../packages/tabs/index.js';
|
||||
import Tab from '../packages/tab/index.js';
|
||||
import Lazyload from '../packages/lazyload/index.js';
|
||||
import ImagePreview from '../packages/image-preview/index.js';
|
||||
import Col from '../packages/col/index.js';
|
||||
import Row from '../packages/row/index.js';
|
||||
import Actionsheet from '../packages/actionsheet/index.js';
|
||||
import Quantity from '../packages/quantity/index.js';
|
||||
import Progress from '../packages/progress/index.js';
|
||||
|
||||
const install = function(Vue) {
|
||||
if (install.installed) return;
|
||||
@ -50,9 +55,13 @@ const install = function(Vue) {
|
||||
Vue.component(Badge.name, Badge);
|
||||
Vue.component(Search.name, Search);
|
||||
Vue.component(Step.name, Step);
|
||||
Vue.component(Tabs.name, Tabs);
|
||||
Vue.component(Tab.name, Tab);
|
||||
Vue.component(Col.name, Col);
|
||||
Vue.component(Row.name, Row);
|
||||
Vue.component(Actionsheet.name, Actionsheet);
|
||||
Vue.component(Quantity.name, Quantity);
|
||||
Vue.component(Progress.name, Progress);
|
||||
};
|
||||
|
||||
// auto install
|
||||
@ -62,7 +71,7 @@ if (typeof window !== 'undefined' && window.Vue) {
|
||||
|
||||
module.exports = {
|
||||
install,
|
||||
version: '0.0.15',
|
||||
version: '0.0.30',
|
||||
Button,
|
||||
Switch,
|
||||
Field,
|
||||
@ -86,8 +95,13 @@ module.exports = {
|
||||
Badge,
|
||||
Search,
|
||||
Step,
|
||||
Tabs,
|
||||
Tab,
|
||||
Lazyload,
|
||||
ImagePreview,
|
||||
Col,
|
||||
Row,
|
||||
Actionsheet
|
||||
Actionsheet,
|
||||
Quantity,
|
||||
Progress
|
||||
};
|
||||
|
@ -1,7 +1,19 @@
|
||||
import Vue from 'vue';
|
||||
import merge from 'src/utils/merge';
|
||||
import PopupManager from './popup-manager';
|
||||
|
||||
let idSeed = 1;
|
||||
let popupContext;
|
||||
if (!window.popupContext) {
|
||||
popupContext = window.popupContext = {
|
||||
idSeed: 1,
|
||||
zIndex: 2000,
|
||||
hasModal: false,
|
||||
instances: {},
|
||||
modalStack: []
|
||||
};
|
||||
} else {
|
||||
popupContext = window.popupContext;
|
||||
}
|
||||
|
||||
const getDOM = function(dom) {
|
||||
if (dom.nodeType === 3) {
|
||||
@ -58,8 +70,8 @@ export default {
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this._popupId = 'popup-' + idSeed++;
|
||||
PopupManager.register(this._popupId, this);
|
||||
this._popupId = 'popup-' + popupContext.idSeed++;
|
||||
PopupManager.register(this._popupId, this, popupContext);
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -86,9 +98,9 @@ export default {
|
||||
const props = merge({}, this, options);
|
||||
const zIndex = props.zIndex;
|
||||
|
||||
// 如果属性中传入了`zIndex`,则覆盖`PopupManager`中对应的`zIndex`
|
||||
// 如果属性中传入了`zIndex`,则覆盖`popupContext`中对应的`zIndex`
|
||||
if (zIndex) {
|
||||
PopupManager.zIndex = zIndex;
|
||||
popupContext.zIndex = zIndex;
|
||||
}
|
||||
|
||||
// 如果显示遮罩层
|
||||
|
@ -1,13 +1,12 @@
|
||||
import Vue from 'vue';
|
||||
import { addClass } from 'src/utils/dom';
|
||||
|
||||
let hasModal = false; // eslint-disable-line
|
||||
|
||||
const getModal = function() {
|
||||
let modalDom = PopupManager.modalDom;
|
||||
if (modalDom) {
|
||||
hasModal = true;
|
||||
PopupManager.popupContext.hasModal = true;
|
||||
} else {
|
||||
hasModal = false;
|
||||
PopupManager.popupContext.hasModal = false;
|
||||
modalDom = document.createElement('div');
|
||||
PopupManager.modalDom = modalDom;
|
||||
|
||||
@ -24,31 +23,26 @@ const getModal = function() {
|
||||
return modalDom;
|
||||
};
|
||||
|
||||
const instances = {};
|
||||
|
||||
const PopupManager = {
|
||||
zIndex: 2000,
|
||||
|
||||
modalStack: [],
|
||||
|
||||
nextZIndex() {
|
||||
return this.zIndex++;
|
||||
return this.popupContext.zIndex++;
|
||||
},
|
||||
|
||||
getInstance(id) {
|
||||
return instances[id];
|
||||
return this.popupContext.instances[id];
|
||||
},
|
||||
|
||||
register(id, instance) {
|
||||
register(id, instance, context) {
|
||||
if (id && instance) {
|
||||
instances[id] = instance;
|
||||
this.popupContext = context;
|
||||
this.popupContext.instances[id] = instance;
|
||||
}
|
||||
},
|
||||
|
||||
deregister(id) {
|
||||
if (id) {
|
||||
instances[id] = null;
|
||||
delete instances[id];
|
||||
this.popupContext.instances[id] = null;
|
||||
delete this.popupContext.instances[id];
|
||||
}
|
||||
},
|
||||
|
||||
@ -56,7 +50,7 @@ const PopupManager = {
|
||||
* 遮罩层点击回调,`closeOnClickOverlay`为`true`时会关闭当前`popup`
|
||||
*/
|
||||
handleOverlayClick() {
|
||||
const topModal = PopupManager.modalStack[PopupManager.modalStack.length - 1];
|
||||
const topModal = this.popupContext.modalStack[this.popupContext.modalStack.length - 1];
|
||||
if (!topModal) return;
|
||||
|
||||
const instance = PopupManager.getInstance(topModal.id);
|
||||
@ -68,7 +62,7 @@ const PopupManager = {
|
||||
openModal(id, zIndex, dom) {
|
||||
if (!id || zIndex === undefined) return;
|
||||
|
||||
const modalStack = this.modalStack;
|
||||
const modalStack = this.popupContext.modalStack;
|
||||
|
||||
for (let i = 0, len = modalStack.length; i < len; i++) {
|
||||
const item = modalStack[i];
|
||||
@ -81,22 +75,18 @@ const PopupManager = {
|
||||
|
||||
addClass(modalDom, 'zan-modal');
|
||||
|
||||
if (dom && dom.parentNode && dom.parentNode.nodeType !== 11) {
|
||||
dom.parentNode.appendChild(modalDom);
|
||||
} else {
|
||||
document.body.appendChild(modalDom);
|
||||
}
|
||||
document.body.appendChild(modalDom);
|
||||
|
||||
if (zIndex) {
|
||||
modalDom.style.zIndex = zIndex;
|
||||
}
|
||||
modalDom.style.display = '';
|
||||
|
||||
this.modalStack.push({ id: id, zIndex: zIndex });
|
||||
this.popupContext.modalStack.push({ id: id, zIndex: zIndex });
|
||||
},
|
||||
|
||||
closeModal(id) {
|
||||
const modalStack = this.modalStack;
|
||||
const modalStack = this.popupContext.modalStack;
|
||||
const modalDom = getModal();
|
||||
|
||||
if (modalStack.length > 0) {
|
||||
@ -118,12 +108,10 @@ const PopupManager = {
|
||||
|
||||
if (modalStack.length === 0) {
|
||||
setTimeout(() => {
|
||||
if (modalStack.length === 0) {
|
||||
if (modalDom.parentNode) modalDom.parentNode.removeChild(modalDom);
|
||||
if (modalDom.parentNode) modalDom.parentNode.removeChild(modalDom);
|
||||
|
||||
modalDom.style.display = 'none';
|
||||
this.modalDom = null;
|
||||
}
|
||||
modalDom.style.display = 'none';
|
||||
this.modalDom = null;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
16
test/unit/specs/actionsheet.spec.js
Normal file
16
test/unit/specs/actionsheet.spec.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { createVue } from '../creater';
|
||||
import ActionSheet from 'packages/actionsheet';
|
||||
|
||||
describe('ActionSheet', () => {
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
vm && vm.destroy();
|
||||
});
|
||||
|
||||
it('create', () => {
|
||||
vm = createVue(ActionSheet);
|
||||
vm.mount();
|
||||
|
||||
expect(vm.el.classList.contains('zan-actionsheet')).to.true;
|
||||
});
|
||||
});
|
20
test/unit/specs/card.spec.js
Normal file
20
test/unit/specs/card.spec.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { createVue } from '../creater';
|
||||
import Card from 'packages/card';
|
||||
|
||||
describe('Card', () => {
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
vm && vm.destroy();
|
||||
});
|
||||
|
||||
it('create', () => {
|
||||
vm = createVue(Card, {
|
||||
title: 'card',
|
||||
desc: 'card',
|
||||
thumb: 'https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg'
|
||||
});
|
||||
vm.mount();
|
||||
|
||||
expect(vm.el.classList.contains('zan-card')).to.true;
|
||||
});
|
||||
});
|
16
test/unit/specs/cell.spec.js
Normal file
16
test/unit/specs/cell.spec.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { createVue } from '../creater';
|
||||
import CellGroup from 'packages/cell-group';
|
||||
|
||||
describe('Cell', () => {
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
vm && vm.destroy();
|
||||
});
|
||||
|
||||
it('cell group create', () => {
|
||||
vm = createVue(CellGroup);
|
||||
vm.mount();
|
||||
|
||||
expect(vm.el.classList.contains('zan-cell-group')).to.true;
|
||||
});
|
||||
});
|
16
test/unit/specs/checkbox.spec.js
Normal file
16
test/unit/specs/checkbox.spec.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { createVue } from '../creater';
|
||||
import Checkbox from 'packages/checkbox';
|
||||
|
||||
describe('Checkbox', () => {
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
vm && vm.destroy();
|
||||
});
|
||||
|
||||
it('create', () => {
|
||||
vm = createVue(Checkbox);
|
||||
vm.mount();
|
||||
|
||||
expect(vm.el.classList.contains('zan-checkbox')).to.true;
|
||||
});
|
||||
});
|
16
test/unit/specs/field.spec.js
Normal file
16
test/unit/specs/field.spec.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { createVue } from '../creater';
|
||||
import Field from 'packages/field';
|
||||
|
||||
describe('Field', () => {
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
vm && vm.destroy();
|
||||
});
|
||||
|
||||
it('create', () => {
|
||||
vm = createVue(Field);
|
||||
vm.mount();
|
||||
|
||||
expect(vm.el.classList.contains('zan-field')).to.true;
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user