97275c2a by simon

默认提交

1 parent 163c37bf
Showing 268 changed files with 3869 additions and 1516 deletions
1 @import "support"; 1 @import "support";
2 2
3 // // Margin
4 // .u-mt-smaller {
5 // margin-top: $marginTopSmaller;
6 // }
7
8 // .u-mt-small {
9 // margin-top: $marginTopSmall;
10 // }
11
12 // .u-mt-medium {
13 // margin-top: $marginTopMedium;
14 // }
15
16 // .u-mt-large {
17 // margin-top: $marginTopLarge;
18 // }
19
20 // .u-mt-larger {
21 // margin-top: $marginTopLarger;
22 // }
23
24 // .u-mb-smaller {
25 // margin-bottom: $marginTopSmaller;
26 // }
27
28 // .u-mb-small {
29 // margin-bottom: $marginTopSmall;
30 // }
31
32 // .u-mb-medium {
33 // margin-bottom: $marginTopMedium;
34 // }
35
36 // .u-mb-large {
37 // margin-bottom: $marginTopLarge;
38 // }
39
40 // .u-mb-larger {
41 // margin-bottom: $marginTopLarger;
42 // }
43
44 // // Padding
45 // .u-pt-smaller {
46 // padding-top: $paddingTopSmaller;
47 // }
48
49 // .u-pt-small {
50 // padding-top: $paddingTopSmall;
51 // }
52
53 // .u-pt-medium {
54 // padding-top: $paddingTopMedium;
55 // }
56
57 // .u-pt-large {
58 // padding-top: $paddingTopLarge;
59 // }
60
61 // .u-pt-larger {
62 // padding-top: $paddingTopLarger;
63 // }
64
65 // .u-pb-smaller {
66 // padding-bottom: $paddingTopSmaller;
67 // }
68
69 // .u-pb-small {
70 // padding-bottom: $paddingTopSmall;
71 // }
72
73 // .u-pb-medium {
74 // padding-bottom: $paddingTopMedium;
75 // }
76
77 // .u-pb-large {
78 // padding-bottom: $paddingTopLarge;
79 // }
80
81 // .u-pb-larger {
82 // padding-bottom: $paddingTopLarger;
83 // }
84
85 // // 布局方位
86 // .u-ta-c {
87 // text-align: center !important;
88 // }
89
90 // .u-ta-l {
91 // text-align: left !important;
92 // }
93
94 // .u-ta-r {
95 // text-align: right !important;
96 // }
97
98 // .u-fl-l {
99 // float: left;
100 // }
101
102 // .u-fl-n {
103 // float: none;
104 // }
105
106 // .u-fl-r {
107 // float: right;
108 // }
109
110 // .u-d-b {
111 // display: block;
112 // }
113
114 // .u-d-i {
115 // display: inline !important;
116 // }
117
118 // .u-d-ib {
119 // display: inline-block !important;
120 // }
121
122 // .u-d-n {
123 // display: none !important;
124 // }
125
126 // .u-d-t {
127 // display: table;
128 // table-layout: fixed;
129 // }
130
131 // .u-d-tc {
132 // display: table-cell;
133 // }
134
135 // .u-va-b {
136 // vertical-align: bottom;
137 // }
138
139 // .u-va-m {
140 // vertical-align: middle;
141 // }
142
143 // .u-va-t {
144 // vertical-align: top;
145 // }
146
147 // // clearfix
148 // .u-clearfix {
149 // @include clearfix;
150 // }
151
152 // // 虚拟格式
153 // .u-cur-d {
154 // cursor: default;
155 // }
156
157 // .u-cur-p {
158 // cursor: pointer;
159 // }
160
161 // // flex
162 // .u-flex {
163 // display: -webkit-box;
164 // display: -webkit-flex;
165 // display: flex;
166 // }
167
168 // .u-flex-item {
169 // -webkit-box-flex: 1;
170 // -webkit-flex: 1;
171 // flex: 1;
172 // }
173
174 // // 小程序中模拟ul、li
175 // .u-ul {
176 // padding-left: 30px;
177 // text-align: left;
178 // display: block;
179 // }
180
181 // .u-li {
182 // position: relative;
183 // font-size: $fontSizeSmall;
184 // line-height: $fontSizeSmall + 4px;
185 // margin-bottom: $marginTopSmall;
186 // &:before {
187 // position: absolute;
188 // content: " ";
189 // top: 14px;
190 // left: -20px;
191 // width: 8px;
192 // height: 8px;
193 // border-radius: 8px;
194 // background-color: $colorBlack;
195 // }
196 // }
197
198
199 3
200 .bis { 4 .bis {
201 background-repeat: no-repeat; 5 background-repeat: no-repeat;
...@@ -213,6 +17,10 @@ ...@@ -213,6 +17,10 @@
213 justify-content: space-between; 17 justify-content: space-between;
214 } 18 }
215 19
20 .fla{
21 display: flex;
22 align-items: center;
23 }
216 24
217 25
218 .fje { 26 .fje {
......
...@@ -57,10 +57,24 @@ Component({ ...@@ -57,10 +57,24 @@ Component({
57 }, 57 },
58 onStepperChange(e) { 58 onStepperChange(e) {
59 let val = e.detail; 59 let val = e.detail;
60 if(val > this.properties.productInfo.maxNum) val = this.properties.productInfo.maxNum; 60 // if(val > this.properties.productInfo.maxNum) val = this.properties.productInfo.maxNum;
61 if(val < this.properties.productInfo.minNum) val = this.properties.productInfo.minNum; 61 // if(val < this.properties.productInfo.minNum) val = this.properties.productInfo.minNum;
62 this.setNum(val); 62 this.setNum(val);
63 }, 63 },
64 onStepperBlur(e) {
65 let val = e.detail.value;
66 this.fixStepperVal(val);
67 },
68 onStepperMod(e) {
69 let val = this.data.num;
70 this.fixStepperVal(val);
71 },
72 fixStepperVal(val) {
73 if (val > this.properties.productInfo.maxNum) val = this.properties.productInfo.maxNum;
74 if (val < this.properties.productInfo.minNum) val = this.properties.productInfo.minNum;
75 this.setNum(val);
76 },
77
64 bindRemarkInput(e) { 78 bindRemarkInput(e) {
65 this.setData({ 79 this.setData({
66 remark: e.detail.value 80 remark: e.detail.value
......
...@@ -44,8 +44,8 @@ ...@@ -44,8 +44,8 @@
44 44
45 .prize { 45 .prize {
46 .image { 46 .image {
47 width: 180px; 47 width: 200px;
48 height: 180px; 48 height: 200px;
49 } 49 }
50 } 50 }
51 51
...@@ -71,9 +71,9 @@ ...@@ -71,9 +71,9 @@
71 } 71 }
72 72
73 .t2 { 73 .t2 {
74 // margin-top: 16px; 74 margin-top: 4px;
75 display: flex; 75 // display: flex;
76 align-items: center; 76 // align-items: center;
77 77
78 .t2-1 { 78 .t2-1 {
79 font-size: 30px; 79 font-size: 30px;
...@@ -82,12 +82,17 @@ ...@@ -82,12 +82,17 @@
82 .t2-2 { 82 .t2-2 {
83 font-size: 20px; 83 font-size: 20px;
84 color: #888888; 84 color: #888888;
85 margin-left: 20px; 85 // margin-left: 20px;
86 }
87
88 .ml-20{
89 margin-left: 20px;
86 } 90 }
87 } 91 }
88 92
89 .t3 { 93 .t3 {
90 font-size: 36px; 94 font-size: 36px;
95
91 } 96 }
92 } 97 }
93 } 98 }
......
...@@ -12,10 +12,11 @@ ...@@ -12,10 +12,11 @@
12 <view class="con"> 12 <view class="con">
13 <view class="tt t1">{{productInfo.seckillName}}</view> 13 <view class="tt t1">{{productInfo.seckillName}}</view>
14 <block wx:if="{{productInfo.minNum == productInfo.maxNum}}"> 14 <block wx:if="{{productInfo.minNum == productInfo.maxNum}}">
15 <!-- <block wx:if="{{1>0}}"> -->
15 <!-- 固定个数 --> 16 <!-- 固定个数 -->
16 <view class="tt t2" wx:if="{{orderStatus != 1}}"> 17 <view class="tt t2 fla" wx:if="{{orderStatus != 1}}">
17 <view class="t2-1">{{productInfo.minNum}}个</view> 18 <view class="t2-1">{{productInfo.minNum}}个</view>
18 <view class="t2-2">数量不可修改</view> 19 <view class="t2-2 ml-20">数量不可修改</view>
19 </view> 20 </view>
20 <view class="num" wx:else>{{num}}个</view> 21 <view class="num" wx:else>{{num}}个</view>
21 </block> 22 </block>
...@@ -23,7 +24,8 @@ ...@@ -23,7 +24,8 @@
23 <!-- 不定个数 --> 24 <!-- 不定个数 -->
24 <view class="tt t2" wx:if="{{orderStatus != 1}}"> 25 <view class="tt t2" wx:if="{{orderStatus != 1}}">
25 <view class="t2-1"> 26 <view class="t2-1">
26 <van-stepper bind:change="onStepperChange" value="{{ num }}" min="{{productInfo.minNum}}" max="{{productInfo.maxNum}}" integer /> 27 <!-- <van-stepper bind:change="onStepperChange" value="{{ num }}" min="{{productInfo.minNum}}" max="{{productInfo.maxNum}}" integer /> -->
28 <van-stepper button-size="32px" input-width="64px" bind:change="onStepperChange" min="{{0}}" value="{{ num }}" integer bind:blur="onStepperBlur" bind:plus="onStepperMod" bind:minus="onStepperMod" />
27 </view> 29 </view>
28 <view class="t2-2">可选填{{productInfo.minNum}}-{{productInfo.maxNum}}个</view> 30 <view class="t2-2">可选填{{productInfo.minNum}}-{{productInfo.maxNum}}个</view>
29 </view> 31 </view>
...@@ -40,7 +42,7 @@ ...@@ -40,7 +42,7 @@
40 </view> 42 </view>
41 <!-- 表单 --> 43 <!-- 表单 -->
42 <view class="table" wx:else> 44 <view class="table" wx:else>
43 <view class="tips">*本活动仅记录订单,无需付款,后期由线下工作人员另行安排支付与配送,请确保收货信息准确。</view> 45 <view class="tips">*本活动仅记录订单,无需付款,后期由线下工作人员另行安排支付与配送,请确保信息准确。</view>
44 <view class="form"> 46 <view class="form">
45 <view class="form-item"> 47 <view class="form-item">
46 <view class="label">收件人:</view> 48 <view class="label">收件人:</view>
......
...@@ -2,7 +2,7 @@ let ENV_CONFIG = require('./env/index'); ...@@ -2,7 +2,7 @@ let ENV_CONFIG = require('./env/index');
2 2
3 const APPID = '' 3 const APPID = ''
4 /** ====每次发布版本记得修改此环境配置==== */ 4 /** ====每次发布版本记得修改此环境配置==== */
5 const ENV = 'Prod'; // Dev Prod 5 const ENV = 'Dev'; // Dev Prod
6 const NET_CONFIG = ENV_CONFIG[ENV]; 6 const NET_CONFIG = ENV_CONFIG[ENV];
7 const MOCKAPI = ENV_CONFIG.mockApi; 7 const MOCKAPI = ENV_CONFIG.mockApi;
8 8
......
...@@ -243,7 +243,7 @@ Page({ ...@@ -243,7 +243,7 @@ Page({
243 price: price * 100 //转成分 243 price: price * 100 //转成分
244 } 244 }
245 }).then((result) => { 245 }).then((result) => {
246 console.log("result:", result); 246 // console.log("result:", result);
247 this.queryAuctionRecordLast().then((res2) => { 247 this.queryAuctionRecordLast().then((res2) => {
248 this.setData({ 248 this.setData({
249 auctionBidSuccessVisible: true 249 auctionBidSuccessVisible: true
...@@ -337,7 +337,7 @@ Page({ ...@@ -337,7 +337,7 @@ Page({
337 let parseData = JSON.parse(socketData); 337 let parseData = JSON.parse(socketData);
338 result = parseData && parseData.content || null; 338 result = parseData && parseData.content || null;
339 } 339 }
340 console.log("result:", result); 340 // console.log("result:", result);
341 341
342 if (!result) return; 342 if (!result) return;
343 let priceInfo = result.list || []; 343 let priceInfo = result.list || [];
......
...@@ -7,6 +7,7 @@ let app = getApp(); ...@@ -7,6 +7,7 @@ let app = getApp();
7 Page({ 7 Page({
8 data: { 8 data: {
9 authorizeVisible: false, 9 authorizeVisible: false,
10 signTipsCompVisible:false,
10 isInit: false, 11 isInit: false,
11 total: 0, 12 total: 0,
12 page: 1, 13 page: 1,
...@@ -70,6 +71,10 @@ Page({ ...@@ -70,6 +71,10 @@ Page({
70 title: curData.auctionName 71 title: curData.auctionName
71 } 72 }
72 }) 73 })
74 } else if(curData.isCanDetail == 2){
75 this.setData({
76 signTipsCompVisible: true,
77 })
73 } else { 78 } else {
74 wx.showModal({ 79 wx.showModal({
75 content: curData.reason || "您未达到进入条件", 80 content: curData.reason || "您未达到进入条件",
...@@ -111,10 +116,21 @@ Page({ ...@@ -111,10 +116,21 @@ Page({
111 }) 116 })
112 }, 117 },
113 118
119 /**
120 * 去验证
121 */
122 toVipLoginHandler() {
123 app.router.push({
124 openType: "redirect",
125 path: "vipLogin"
126 })
127 },
128
114 // 隐藏蒙层 129 // 隐藏蒙层
115 hideMask() { 130 hideMask() {
116 this.setData({ 131 this.setData({
117 authorizeVisible: false, 132 authorizeVisible: false,
133 signTipsCompVisible: false,
118 }) 134 })
119 }, 135 },
120 // 子组件事件 136 // 子组件事件
...@@ -125,6 +141,19 @@ Page({ ...@@ -125,6 +141,19 @@ Page({
125 } = evt.detail; 141 } = evt.detail;
126 switch (name) { 142 switch (name) {
127 143
144
145 // 去验证
146 case "_evt_to_verify":
147 this.hideMask();
148 this.toVipLoginHandler();
149 break;
150
151
152 // 暂不验证
153 case "_evt_not_verify":
154 this.hideMask();
155 break;
156
128 // 隐藏弹窗 157 // 隐藏弹窗
129 case "_evt_hide_mask": 158 case "_evt_hide_mask":
130 this.hideMask(); 159 this.hideMask();
......
...@@ -36,3 +36,7 @@ ...@@ -36,3 +36,7 @@
36 <van-popup show="{{ authorizeVisible }}"> 36 <van-popup show="{{ authorizeVisible }}">
37 <authorize-comp bind:evtcomp="evtcomp"></authorize-comp> 37 <authorize-comp bind:evtcomp="evtcomp"></authorize-comp>
38 </van-popup> 38 </van-popup>
39
40 <van-popup show="{{ signTipsCompVisible }}">
41 <sign-tips-comp bind:evtcomp="evtcomp"></sign-tips-comp>
42 </van-popup>
......
...@@ -147,7 +147,7 @@ Page({ ...@@ -147,7 +147,7 @@ Page({
147 this.setData({ 147 this.setData({
148 productInfo: result 148 productInfo: result
149 }) 149 })
150 console.log("result:", result); 150 // console.log("result:", result);
151 resolve(); 151 resolve();
152 }).catch((err) => { 152 }).catch((err) => {
153 if (err.code == 1002) { 153 if (err.code == 1002) {
...@@ -178,7 +178,7 @@ Page({ ...@@ -178,7 +178,7 @@ Page({
178 url: app.api.seckillSubmit, 178 url: app.api.seckillSubmit,
179 data: data 179 data: data
180 }).then((result) => { 180 }).then((result) => {
181 console.log("result:", result); 181 // console.log("result:", result);
182 this.setData({ 182 this.setData({
183 orderStatus: 1, 183 orderStatus: 1,
184 }) 184 })
......
...@@ -7,6 +7,7 @@ let app = getApp(); ...@@ -7,6 +7,7 @@ let app = getApp();
7 Page({ 7 Page({
8 data: { 8 data: {
9 authorizeVisible: false, 9 authorizeVisible: false,
10 signTipsCompVisible:false,
10 isInit: false, 11 isInit: false,
11 total: 0, 12 total: 0,
12 page: 1, 13 page: 1,
...@@ -63,6 +64,7 @@ Page({ ...@@ -63,6 +64,7 @@ Page({
63 onDetailHandler(evt) { 64 onDetailHandler(evt) {
64 let curData = getBindtapData(evt); 65 let curData = getBindtapData(evt);
65 console.log("curData:", curData); 66 console.log("curData:", curData);
67 // curData.isCanDetail = 2;
66 if (curData.status == 0 || curData.status == 1) { 68 if (curData.status == 0 || curData.status == 1) {
67 if (curData.isCanDetail == 1) { 69 if (curData.isCanDetail == 1) {
68 app.router.push({ 70 app.router.push({
...@@ -71,6 +73,10 @@ Page({ ...@@ -71,6 +73,10 @@ Page({
71 code: curData.seckillCode, 73 code: curData.seckillCode,
72 } 74 }
73 }) 75 })
76 } else if(curData.isCanDetail == 2){
77 this.setData({
78 signTipsCompVisible: true,
79 })
74 } else { 80 } else {
75 wx.showModal({ 81 wx.showModal({
76 content: curData.reason || "您未达到进入条件", 82 content: curData.reason || "您未达到进入条件",
...@@ -106,10 +112,21 @@ Page({ ...@@ -106,10 +112,21 @@ Page({
106 }) 112 })
107 }, 113 },
108 114
115 /**
116 * 去验证
117 */
118 toVipLoginHandler() {
119 app.router.push({
120 openType: "redirect",
121 path: "vipLogin"
122 })
123 },
124
109 // 隐藏蒙层 125 // 隐藏蒙层
110 hideMask() { 126 hideMask() {
111 this.setData({ 127 this.setData({
112 authorizeVisible: false, 128 authorizeVisible: false,
129 signTipsCompVisible: false,
113 }) 130 })
114 }, 131 },
115 // 子组件事件 132 // 子组件事件
...@@ -120,6 +137,18 @@ Page({ ...@@ -120,6 +137,18 @@ Page({
120 } = evt.detail; 137 } = evt.detail;
121 switch (name) { 138 switch (name) {
122 139
140 // 去验证
141 case "_evt_to_verify":
142 this.hideMask();
143 this.toVipLoginHandler();
144 break;
145
146 // 暂不验证
147 case "_evt_not_verify":
148 this.hideMask();
149 break;
150
151
123 // 隐藏弹窗 152 // 隐藏弹窗
124 case "_evt_hide_mask": 153 case "_evt_hide_mask":
125 this.hideMask(); 154 this.hideMask();
......
...@@ -36,3 +36,7 @@ ...@@ -36,3 +36,7 @@
36 <van-popup show="{{ authorizeVisible }}"> 36 <van-popup show="{{ authorizeVisible }}">
37 <authorize-comp bind:evtcomp="evtcomp"></authorize-comp> 37 <authorize-comp bind:evtcomp="evtcomp"></authorize-comp>
38 </van-popup> 38 </van-popup>
39
40 <van-popup show="{{ signTipsCompVisible }}">
41 <sign-tips-comp bind:evtcomp="evtcomp"></sign-tips-comp>
42 </van-popup>
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({ 2 VantComponent({
4 mixins: [safeArea()],
5 props: { 3 props: {
6 show: Boolean, 4 show: Boolean,
7 title: String, 5 title: String,
8 cancelText: String, 6 cancelText: String,
7 description: String,
8 round: {
9 type: Boolean,
10 value: true
11 },
9 zIndex: { 12 zIndex: {
10 type: Number, 13 type: Number,
11 value: 100 14 value: 100
...@@ -21,6 +24,14 @@ VantComponent({ ...@@ -21,6 +24,14 @@ VantComponent({
21 closeOnClickOverlay: { 24 closeOnClickOverlay: {
22 type: Boolean, 25 type: Boolean,
23 value: true 26 value: true
27 },
28 closeOnClickAction: {
29 type: Boolean,
30 value: true
31 },
32 safeAreaInsetBottom: {
33 type: Boolean,
34 value: true
24 } 35 }
25 }, 36 },
26 methods: { 37 methods: {
...@@ -29,6 +40,9 @@ VantComponent({ ...@@ -29,6 +40,9 @@ VantComponent({
29 const item = this.data.actions[index]; 40 const item = this.data.actions[index];
30 if (item && !item.disabled && !item.loading) { 41 if (item && !item.disabled && !item.loading) {
31 this.$emit('select', item); 42 this.$emit('select', item);
43 if (this.data.closeOnClickAction) {
44 this.onClose();
45 }
32 } 46 }
33 }, 47 },
34 onCancel() { 48 onCancel() {
...@@ -36,6 +50,10 @@ VantComponent({ ...@@ -36,6 +50,10 @@ VantComponent({
36 }, 50 },
37 onClose() { 51 onClose() {
38 this.$emit('close'); 52 this.$emit('close');
53 },
54 onClickOverlay() {
55 this.$emit('click-overlay');
56 this.onClose();
39 } 57 }
40 } 58 }
41 }); 59 });
......
...@@ -3,12 +3,13 @@ ...@@ -3,12 +3,13 @@
3 <van-popup 3 <van-popup
4 show="{{ show }}" 4 show="{{ show }}"
5 position="bottom" 5 position="bottom"
6 round="{{ round }}"
6 z-index="{{ zIndex }}" 7 z-index="{{ zIndex }}"
7 overlay="{{ overlay }}" 8 overlay="{{ overlay }}"
8 custom-class="van-action-sheet" 9 custom-class="van-action-sheet"
9 safe-area-inset-bottom="{{ safeAreaInsetBottom }}" 10 safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
10 close-on-click-overlay="{{ closeOnClickOverlay }}" 11 close-on-click-overlay="{{ closeOnClickOverlay }}"
11 bind:close="onClose" 12 bind:close="onClickOverlay"
12 > 13 >
13 <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header"> 14 <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
14 {{ title }} 15 {{ title }}
...@@ -18,12 +19,16 @@ ...@@ -18,12 +19,16 @@
18 bind:click="onClose" 19 bind:click="onClose"
19 /> 20 />
20 </view> 21 </view>
22 <view wx:if="{{ description }}" class="van-action-sheet__description">
23 {{ description }}
24 </view>
21 <view wx:if="{{ actions && actions.length }}"> 25 <view wx:if="{{ actions && actions.length }}">
22 <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 --> 26 <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
23 <button 27 <button
24 wx:for="{{ actions }}" 28 wx:for="{{ actions }}"
25 wx:key="index" 29 wx:key="index"
26 open-type="{{ item.openType }}" 30 open-type="{{ item.openType }}"
31 style="{{ item.color ? 'color: ' + item.color : '' }}"
27 class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}" 32 class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
28 hover-class="van-action-sheet__item--hover" 33 hover-class="van-action-sheet__item--hover"
29 data-index="{{ index }}" 34 data-index="{{ index }}"
...@@ -33,7 +38,7 @@ ...@@ -33,7 +38,7 @@
33 {{ item.name }} 38 {{ item.name }}
34 <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text> 39 <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
35 </block> 40 </block>
36 <van-loading wx:else size="20px" /> 41 <van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
37 </button> 42 </button>
38 </view> 43 </view>
39 <slot /> 44 <slot />
......
1 @import '../common/index.wxss';.van-action-sheet{max-height:90%!important;color:#333}.van-action-sheet__cancel,.van-action-sheet__item{height:50px;font-size:16px;line-height:50px;text-align:center;background-color:#fff}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel{height:60px}.van-action-sheet__cancel:before{display:block;height:10px;background-color:#f8f8f8;content:" "}.van-action-sheet__item--disabled{color:#c9c9c9}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff}.van-action-sheet__subname{margin-left:5px;font-size:12px;color:#7d7e80}.van-action-sheet__header{font-size:16px;font-weight:500;line-height:44px;text-align:center}.van-action-sheet__close{position:absolute!important;top:0;right:0;padding:0 15px;font-size:18px!important;line-height:inherit!important;color:#999}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-action-sheet{max-height:90%!important;max-height:var(--action-sheet-max-height,90%)!important;color:#323233;color:var(--action-sheet-item-text-color,#323233)}.van-action-sheet__cancel,.van-action-sheet__item{text-align:center;font-size:16px;font-size:var(--action-sheet-item-font-size,16px);line-height:50px;line-height:var(--action-sheet-item-height,50px);background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-action-sheet__cancel:before{display:block;content:" ";height:8px;height:var(--action-sheet-cancel-padding-top,8px);background-color:#f8f8f8;background-color:var(--action-sheet-cancel-padding-color,#f8f8f8)}.van-action-sheet__item--disabled{color:#c8c9cc;color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{margin-left:4px;margin-left:var(--padding-base,4px);font-size:12px;font-size:var(--action-sheet-subname-font-size,12px);color:#7d7e80;color:var(--action-sheet-subname-color,#7d7e80)}.van-action-sheet__header{text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--action-sheet-header-font-size,16px);line-height:44px;line-height:var(--action-sheet-header-height,44px)}.van-action-sheet__description{text-align:center;padding:16px;padding:var(--padding-md,16px);color:#7d7e80;color:var(--action-sheet-description-color,#7d7e80);font-size:14px;font-size:var(--action-sheet-description-font-size,14px);line-height:20px;line-height:var(--action-sheet-description-line-height,20px)}.van-action-sheet__close{position:absolute!important;top:0;right:0;line-height:inherit!important;padding:0 12px;padding:var(--action-sheet-close-icon-padding,0 12px);font-size:18px!important;font-size:var(--action-sheet-close-icon-size,18px)!important;color:#969799;color:var(--action-sheet-close-icon-color,#969799)}.van-action-sheet__loading{display:-webkit-flex!important;display:flex!important;height:50px;height:var(--action-sheet-item-height,50px)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { pickerProps } from '../picker/shared';
3 const COLUMNSPLACEHOLDERCODE = '000000';
2 VantComponent({ 4 VantComponent({
3 classes: ['active-class', 'toolbar-class', 'column-class'], 5 classes: ['active-class', 'toolbar-class', 'column-class'],
4 props: { 6 props: Object.assign(Object.assign({}, pickerProps), { value: String, areaList: {
5 title: String,
6 value: String,
7 loading: Boolean,
8 cancelButtonText: String,
9 confirmButtonText: String,
10 itemHeight: {
11 type: Number,
12 value: 44
13 },
14 visibleItemCount: {
15 type: Number,
16 value: 5
17 },
18 columnsNum: {
19 type: [String, Number],
20 value: 3
21 },
22 areaList: {
23 type: Object, 7 type: Object,
24 value: {} 8 value: {}
25 } 9 }, columnsNum: {
26 }, 10 type: null,
11 value: 3
12 }, columnsPlaceholder: {
13 type: Array,
14 observer(val) {
15 this.setData({
16 typeToColumnsPlaceholder: {
17 province: val[0] || '',
18 city: val[1] || '',
19 county: val[2] || '',
20 }
21 });
22 }
23 } }),
27 data: { 24 data: {
28 columns: [{ values: [] }, { values: [] }, { values: [] }], 25 columns: [{ values: [] }, { values: [] }, { values: [] }],
29 displayColumns: [{ values: [] }, { values: [] }, { values: [] }] 26 displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
27 typeToColumnsPlaceholder: {}
30 }, 28 },
31 watch: { 29 watch: {
32 value(value) { 30 value(value) {
...@@ -35,11 +33,16 @@ VantComponent({ ...@@ -35,11 +33,16 @@ VantComponent({
35 }, 33 },
36 areaList: 'setValues', 34 areaList: 'setValues',
37 columnsNum(value) { 35 columnsNum(value) {
38 this.set({ 36 this.setData({
39 displayColumns: this.data.columns.slice(0, +value) 37 displayColumns: this.data.columns.slice(0, +value)
40 }); 38 });
41 } 39 }
42 }, 40 },
41 mounted() {
42 setTimeout(() => {
43 this.setValues();
44 }, 0);
45 },
43 methods: { 46 methods: {
44 getPicker() { 47 getPicker() {
45 if (this.picker == null) { 48 if (this.picker == null) {
...@@ -51,20 +54,38 @@ VantComponent({ ...@@ -51,20 +54,38 @@ VantComponent({
51 this.emit('cancel', event.detail); 54 this.emit('cancel', event.detail);
52 }, 55 },
53 onConfirm(event) { 56 onConfirm(event) {
54 this.emit('confirm', event.detail); 57 const { index } = event.detail;
58 let { value } = event.detail;
59 value = this.parseOutputValues(value);
60 this.emit('confirm', { value, index });
55 }, 61 },
56 emit(type, detail) { 62 emit(type, detail) {
57 detail.values = detail.value; 63 detail.values = detail.value;
58 delete detail.value; 64 delete detail.value;
59 this.$emit(type, detail); 65 this.$emit(type, detail);
60 }, 66 },
67 // parse output columns data
68 parseOutputValues(values) {
69 const { columnsPlaceholder } = this.data;
70 return values.map((value, index) => {
71 // save undefined value
72 if (!value)
73 return value;
74 value = JSON.parse(JSON.stringify(value));
75 if (!value.code || value.name === columnsPlaceholder[index]) {
76 value.code = '';
77 value.name = '';
78 }
79 return value;
80 });
81 },
61 onChange(event) { 82 onChange(event) {
62 const { index, picker, value } = event.detail; 83 const { index, picker, value } = event.detail;
63 this.code = value[index].code; 84 this.code = value[index].code;
64 this.setValues().then(() => { 85 this.setValues().then(() => {
65 this.$emit('change', { 86 this.$emit('change', {
66 picker, 87 picker,
67 values: picker.getValues(), 88 values: this.parseOutputValues(picker.getValues()),
68 index 89 index
69 }); 90 });
70 }); 91 });
...@@ -74,6 +95,7 @@ VantComponent({ ...@@ -74,6 +95,7 @@ VantComponent({
74 return (areaList && areaList[`${type}_list`]) || {}; 95 return (areaList && areaList[`${type}_list`]) || {};
75 }, 96 },
76 getList(type, code) { 97 getList(type, code) {
98 const { typeToColumnsPlaceholder } = this.data;
77 let result = []; 99 let result = [];
78 if (type !== 'province' && !code) { 100 if (type !== 'province' && !code) {
79 return result; 101 return result;
...@@ -90,6 +112,14 @@ VantComponent({ ...@@ -90,6 +112,14 @@ VantComponent({
90 } 112 }
91 result = result.filter(item => item.code.indexOf(code) === 0); 113 result = result.filter(item => item.code.indexOf(code) === 0);
92 } 114 }
115 if (typeToColumnsPlaceholder[type] && result.length) {
116 // set columns placeholder
117 const codeFill = type === 'province' ? '' : type === 'city' ? COLUMNSPLACEHOLDERCODE.slice(2, 4) : COLUMNSPLACEHOLDERCODE.slice(4, 6);
118 result.unshift({
119 code: `${code}${codeFill}`,
120 name: typeToColumnsPlaceholder[type]
121 });
122 }
93 return result; 123 return result;
94 }, 124 },
95 getIndex(type, code) { 125 getIndex(type, code) {
...@@ -109,7 +139,18 @@ VantComponent({ ...@@ -109,7 +139,18 @@ VantComponent({
109 }, 139 },
110 setValues() { 140 setValues() {
111 const county = this.getConfig('county'); 141 const county = this.getConfig('county');
112 let code = this.code || Object.keys(county)[0] || ''; 142 let { code } = this;
143 if (!code) {
144 if (this.data.columnsPlaceholder.length) {
145 code = COLUMNSPLACEHOLDERCODE;
146 }
147 else if (Object.keys(county)[0]) {
148 code = Object.keys(county)[0];
149 }
150 else {
151 code = '';
152 }
153 }
113 const province = this.getList('province'); 154 const province = this.getList('province');
114 const city = this.getList('city', code.slice(0, 2)); 155 const city = this.getList('city', code.slice(0, 2));
115 const picker = this.getPicker(); 156 const picker = this.getPicker();
...@@ -120,7 +161,6 @@ VantComponent({ ...@@ -120,7 +161,6 @@ VantComponent({
120 stack.push(picker.setColumnValues(0, province, false)); 161 stack.push(picker.setColumnValues(0, province, false));
121 stack.push(picker.setColumnValues(1, city, false)); 162 stack.push(picker.setColumnValues(1, city, false));
122 if (city.length && code.slice(2, 4) === '00') { 163 if (city.length && code.slice(2, 4) === '00') {
123 ;
124 [{ code }] = city; 164 [{ code }] = city;
125 } 165 }
126 stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false)); 166 stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
...@@ -162,8 +202,8 @@ VantComponent({ ...@@ -162,8 +202,8 @@ VantComponent({
162 } 202 }
163 return area; 203 return area;
164 }, 204 },
165 reset() { 205 reset(code) {
166 this.code = ''; 206 this.code = code || '';
167 return this.setValues(); 207 return this.setValues();
168 } 208 }
169 } 209 }
......
1 @import '../common/index.wxss';.van-badge-group{width:85px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-badge{display:block;padding:20px 12px 20px 9px;overflow:hidden;font-size:14px;line-height:1.4;color:#7d7e80;word-break:break-all;background-color:#f8f8f8;border-left:3px solid transparent;box-sizing:border-box;-webkit-user-select:none;user-select:none}.van-badge--hover{background-color:#f2f3f5}.van-badge:after{border-bottom-width:1px}.van-badge--active{font-weight:700;color:#333;border-color:#f44}.van-badge--active:after{border-right-width:1px}.van-badge--active,.van-badge--active.van-badge--hover{background-color:#fff}.van-badge__text{position:relative}
...\ No newline at end of file ...\ No newline at end of file
...@@ -4,7 +4,11 @@ import { openType } from '../mixins/open-type'; ...@@ -4,7 +4,11 @@ import { openType } from '../mixins/open-type';
4 VantComponent({ 4 VantComponent({
5 mixins: [button, openType], 5 mixins: [button, openType],
6 classes: ['hover-class', 'loading-class'], 6 classes: ['hover-class', 'loading-class'],
7 data: {
8 style: ''
9 },
7 props: { 10 props: {
11 icon: String,
8 plain: Boolean, 12 plain: Boolean,
9 block: Boolean, 13 block: Boolean,
10 round: Boolean, 14 round: Boolean,
...@@ -13,6 +17,11 @@ VantComponent({ ...@@ -13,6 +17,11 @@ VantComponent({
13 hairline: Boolean, 17 hairline: Boolean,
14 disabled: Boolean, 18 disabled: Boolean,
15 loadingText: String, 19 loadingText: String,
20 customStyle: String,
21 loadingType: {
22 type: String,
23 value: 'circular'
24 },
16 type: { 25 type: {
17 type: String, 26 type: String,
18 value: 'default' 27 value: 'default'
...@@ -24,6 +33,29 @@ VantComponent({ ...@@ -24,6 +33,29 @@ VantComponent({
24 loadingSize: { 33 loadingSize: {
25 type: String, 34 type: String,
26 value: '20px' 35 value: '20px'
36 },
37 color: {
38 type: String,
39 observer(color) {
40 let style = '';
41 if (color) {
42 style += `color: ${this.data.plain ? color : 'white'};`;
43 if (!this.data.plain) {
44 // Use background instead of backgroundColor to make linear-gradient work
45 style += `background: ${color};`;
46 }
47 // hide border when color is linear-gradient
48 if (color.indexOf('gradient') !== -1) {
49 style += 'border: 0;';
50 }
51 else {
52 style += `border-color: ${color};`;
53 }
54 }
55 if (style !== this.data.style) {
56 this.setData({ style });
57 }
58 }
27 } 59 }
28 }, 60 },
29 methods: { 61 methods: {
......
1 { 1 {
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-icon": "../icon/index",
4 "van-loading": "../loading/index" 5 "van-loading": "../loading/index"
5 } 6 }
6 }
...\ No newline at end of file ...\ No newline at end of file
7 }
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
3 <button 3 <button
4 id="{{ id }}" 4 id="{{ id }}"
5 class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}" 5 class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
6 open-type="{{ openType }}"
7 hover-class="van-button--active hover-class" 6 hover-class="van-button--active hover-class"
8 lang="{{ lang }}" 7 lang="{{ lang }}"
8 style="{{ style }} {{ customStyle }}"
9 open-type="{{ openType }}"
9 business-id="{{ businessId }}" 10 business-id="{{ businessId }}"
10 session-from="{{ sessionFrom }}" 11 session-from="{{ sessionFrom }}"
11 send-message-title="{{ sendMessageTitle }}" 12 send-message-title="{{ sendMessageTitle }}"
...@@ -26,7 +27,8 @@ ...@@ -26,7 +27,8 @@
26 <van-loading 27 <van-loading
27 custom-class="loading-class" 28 custom-class="loading-class"
28 size="{{ loadingSize }}" 29 size="{{ loadingSize }}"
29 color="{{ type === 'default' ? '#c9c9c9' : '' }}" 30 type="{{ loadingType }}"
31 color="{{ type === 'default' ? '#c9c9c9' : 'white' }}"
30 /> 32 />
31 <view 33 <view
32 wx:if="{{ loadingText }}" 34 wx:if="{{ loadingText }}"
...@@ -35,5 +37,16 @@ ...@@ -35,5 +37,16 @@
35 {{ loadingText }} 37 {{ loadingText }}
36 </view> 38 </view>
37 </block> 39 </block>
38 <slot wx:else /> 40 <block wx:else>
41 <van-icon
42 wx:if="{{ icon }}"
43 size="1.2em"
44 name="{{ icon }}"
45 class="van-button__icon"
46 custom-style="line-height: inherit;"
47 />
48 <view class="van-button__text">
49 <slot />
50 </view>
51 </block>
39 </button> 52 </button>
......
1 @import '../common/index.wxss';.van-button{position:relative;display:inline-block;height:44px;padding:0;font-size:16px;line-height:42px;text-align:center;vertical-align:middle;box-sizing:border-box;border-radius:2px;-webkit-appearance:none;-webkit-text-size-adjust:100%}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#333;background-color:#fff;border:1px solid #eee}.van-button--primary{color:#fff;background-color:#07c160;border:1px solid #07c160}.van-button--info{color:#fff;background-color:#1989fa;border:1px solid #1989fa}.van-button--danger{color:#fff;background-color:#f44;border:1px solid #f44}.van-button--warning{color:#fff;background-color:#ff976a;border:1px solid #ff976a}.van-button--plain{background-color:#fff}.van-button--plain.van-button--primary{color:#07c160}.van-button--plain.van-button--info{color:#1989fa}.van-button--plain.van-button--danger{color:#f44}.van-button--plain.van-button--warning{color:#ff976a}.van-button--large{width:100%;height:50px;line-height:48px}.van-button--normal{padding:0 15px;font-size:14px}.van-button--small{height:30px;min-width:60px;padding:0 8px;font-size:12px;line-height:28px}.van-button--mini{display:inline-block;width:50px;height:22px;font-size:10px;line-height:20px}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:block;width:100%}.van-button--round{border-radius:10em}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5}.van-button__loading-text{margin-left:5px;display:inline-block;vertical-align:middle}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-width:1px;border-color:inherit;border-radius:4px}.van-button--hairline.van-button--round:after{border-radius:10em}.van-button--hairline.van-button--square:after{border-radius:0}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;line-height:20px;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background-color:#fff;background-color:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:1px solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background-color:#07c160;background-color:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:1px solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background-color:#1989fa;background-color:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:1px solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background-color:#ee0a24;background-color:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:1px solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background-color:#ff976a;background-color:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:1px solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background-color:#fff;background-color:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
34 <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view> 34 <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view>
35 <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view> 35 <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
36 <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view> 36 <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
37 <slot name="bottom" />
37 </view> 38 </view>
38 </view> 39 </view>
39 </view> 40 </view>
......
1 @import '../common/index.wxss';.van-card{position:relative;padding:5px 15px;font-size:12px;color:#333;background-color:#fafafa;box-sizing:border-box}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;width:90px;height:90px;margin-right:10px;-webkit-flex:none;flex:none}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;min-width:0;-webkit-flex:1;flex:1}.van-card__desc,.van-card__title{word-break:break-all}.van-card__title{font-weight:700;line-height:16px}.van-card__desc{color:#7d7e80}.van-card__bottom,.van-card__desc{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#f44}.van-card__origin-price{display:inline-block;margin-left:5px;font-size:10px;color:#7d7e80;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{width:100%;text-align:right;-webkit-flex:none;flex:none}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-card{position:relative;box-sizing:border-box;padding:8px 16px;padding:var(--card-padding,8px 16px);font-size:12px;font-size:var(--card-font-size,12px);color:#323233;color:var(--card-text-color,#323233);background-color:#fafafa;background-color:var(--card-background-color,#fafafa)}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;-webkit-flex:none;flex:none;width:90px;width:var(--card-thumb-size,90px);height:90px;height:var(--card-thumb-size,90px);margin-right:8px;margin-right:var(--padding-xs,8px)}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;-webkit-flex:1;flex:1;min-width:0}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:16px;line-height:var(--card-title-line-height,16px)}.van-card__desc{line-height:20px;line-height:var(--card-desc-line-height,20px);color:#7d7e80;color:var(--card-desc-color,#7d7e80)}.van-card__bottom{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#ee0a24;color:var(--card-price-color,#ee0a24)}.van-card__origin-price{display:inline-block;margin-left:5px;text-decoration:line-through;font-size:10px;font-size:var(--card-origin-price-font-size,10px);color:#7d7e80;color:var(--card-origin-price-color,#7d7e80)}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{-webkit-flex:none;flex:none;width:100%;text-align:right}
...\ No newline at end of file ...\ No newline at end of file
......
1 @import '../common/index.wxss';.van-cell-group__title{font-size:14px;padding:15px 15px 5px;color:#999;line-height:16px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -22,6 +22,7 @@ VantComponent({ ...@@ -22,6 +22,7 @@ VantComponent({
22 titleWidth: String, 22 titleWidth: String,
23 customStyle: String, 23 customStyle: String,
24 arrowDirection: String, 24 arrowDirection: String,
25 useLabelSlot: Boolean,
25 border: { 26 border: {
26 type: Boolean, 27 type: Boolean,
27 value: true 28 value: true
......
...@@ -19,11 +19,13 @@ ...@@ -19,11 +19,13 @@
19 style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}" 19 style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}"
20 class="van-cell__title title-class" 20 class="van-cell__title title-class"
21 > 21 >
22 <block wx:if="{{ title }}"> 22 <block wx:if="{{ title }}">{{ title }}</block>
23 {{ title }}
24 <view wx:if="{{ label }}" class="van-cell__label label-class">{{ label }}</view>
25 </block>
26 <slot wx:else name="title" /> 23 <slot wx:else name="title" />
24
25 <view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
26 <slot wx:if="{{ useLabelSlot }}" name="label" />
27 <block wx:elif="{{ label }}">{{ label }}</block>
28 </view>
27 </view> 29 </view>
28 30
29 <view class="van-cell__value value-class"> 31 <view class="van-cell__value value-class">
......
1 @import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;width:100%;padding:10px 15px;font-size:14px;line-height:24px;color:#333;background-color:#fff;box-sizing:border-box}.van-cell:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:auto;left:15px;right:0;bottom:0;-webkit-transform:scaleY(.5);transform:scaleY(.5);border-bottom:1px solid #eee}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff}.van-cell__label{margin-top:3px;font-size:12px;line-height:18px;color:#999}.van-cell__value{overflow:hidden;color:#999;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;height:24px;font-size:16px;-webkit-align-items:center;align-items:center}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#999}.van-cell__left-icon{line-height:24px;vertical-align:middle}.van-cell__right-icon{line-height:24px}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;left:7px;font-size:14px;color:#f44;content:"*"}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-bottom:12px}.van-cell--large .van-cell__title{font-size:16px}.van-cell--large .van-cell__label{font-size:14px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:auto;right:0;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -5,29 +5,34 @@ VantComponent({ ...@@ -5,29 +5,34 @@ VantComponent({
5 name: 'checkbox', 5 name: 'checkbox',
6 type: 'descendant', 6 type: 'descendant',
7 linked(target) { 7 linked(target) {
8 const { value, disabled } = this.data; 8 this.children = this.children || [];
9 target.set({ 9 this.children.push(target);
10 value: value.indexOf(target.data.name) !== -1, 10 this.updateChild(target);
11 disabled: disabled || target.data.disabled 11 },
12 }); 12 unlinked(target) {
13 this.children = this.children.filter((child) => child !== target);
13 } 14 }
14 }, 15 },
15 props: { 16 props: {
16 max: Number, 17 max: Number,
17 value: Array, 18 value: {
18 disabled: Boolean 19 type: Array,
20 observer: 'updateChildren'
21 },
22 disabled: {
23 type: Boolean,
24 observer: 'updateChildren'
25 }
19 }, 26 },
20 watch: { 27 methods: {
21 value(value) { 28 updateChildren() {
22 const children = this.getRelationNodes('../checkbox/index'); 29 (this.children || []).forEach((child) => this.updateChild(child));
23 children.forEach(child => {
24 child.set({ value: value.indexOf(child.data.name) !== -1 });
25 });
26 }, 30 },
27 disabled(disabled) { 31 updateChild(child) {
28 const children = this.getRelationNodes('../checkbox/index'); 32 const { value, disabled } = this.data;
29 children.forEach(child => { 33 child.setData({
30 child.set({ disabled: disabled || child.data.disabled }); 34 value: value.indexOf(child.data.name) !== -1,
35 disabled: disabled || child.data.disabled
31 }); 36 });
32 } 37 }
33 } 38 }
......
1 { 1 {
2 "component": true, 2 "component": true
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 } 3 }
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { addUnit } from '../common/utils';
3 function emit(target, value) {
4 target.$emit('input', value);
5 target.$emit('change', value);
6 }
2 VantComponent({ 7 VantComponent({
3 field: true, 8 field: true,
4 relation: { 9 relation: {
5 name: 'checkbox-group', 10 name: 'checkbox-group',
6 type: 'ancestor' 11 type: 'ancestor',
12 linked(target) {
13 this.parent = target;
14 },
15 unlinked() {
16 this.parent = null;
17 }
7 }, 18 },
8 classes: ['icon-class', 'label-class'], 19 classes: ['icon-class', 'label-class'],
9 props: { 20 props: {
10 value: null, 21 value: Boolean,
11 disabled: Boolean, 22 disabled: Boolean,
12 useIconSlot: Boolean, 23 useIconSlot: Boolean,
13 checkedColor: String, 24 checkedColor: String,
...@@ -16,52 +27,61 @@ VantComponent({ ...@@ -16,52 +27,61 @@ VantComponent({
16 shape: { 27 shape: {
17 type: String, 28 type: String,
18 value: 'round' 29 value: 'round'
30 },
31 iconSize: {
32 type: null,
33 observer: 'setSizeWithUnit'
19 } 34 }
20 }, 35 },
36 data: {
37 sizeWithUnit: '20px'
38 },
21 methods: { 39 methods: {
22 emitChange(value) { 40 emitChange(value) {
23 const parent = this.getRelationNodes('../checkbox-group/index')[0]; 41 if (this.parent) {
24 if (parent) { 42 this.setParentValue(this.parent, value);
25 this.setParentValue(parent, value);
26 } 43 }
27 else { 44 else {
28 this.$emit('input', value); 45 emit(this, value);
29 this.$emit('change', value);
30 } 46 }
31 }, 47 },
32 toggle() { 48 toggle() {
33 if (!this.data.disabled) { 49 const { disabled, value } = this.data;
34 this.emitChange(!this.data.value); 50 if (!disabled) {
51 this.emitChange(!value);
35 } 52 }
36 }, 53 },
37 onClickLabel() { 54 onClickLabel() {
38 if (!this.data.disabled && !this.data.labelDisabled) { 55 const { labelDisabled, disabled, value } = this.data;
39 this.emitChange(!this.data.value); 56 if (!disabled && !labelDisabled) {
57 this.emitChange(!value);
40 } 58 }
41 }, 59 },
42 setParentValue(parent, value) { 60 setParentValue(parent, value) {
43 const parentValue = parent.data.value.slice(); 61 const parentValue = parent.data.value.slice();
44 const { name } = this.data; 62 const { name } = this.data;
63 const { max } = parent.data;
45 if (value) { 64 if (value) {
46 if (parent.data.max && parentValue.length >= parent.data.max) { 65 if (max && parentValue.length >= max) {
47 return; 66 return;
48 } 67 }
49 /* istanbul ignore else */
50 if (parentValue.indexOf(name) === -1) { 68 if (parentValue.indexOf(name) === -1) {
51 parentValue.push(name); 69 parentValue.push(name);
52 parent.$emit('input', parentValue); 70 emit(parent, parentValue);
53 parent.$emit('change', parentValue);
54 } 71 }
55 } 72 }
56 else { 73 else {
57 const index = parentValue.indexOf(name); 74 const index = parentValue.indexOf(name);
58 /* istanbul ignore else */
59 if (index !== -1) { 75 if (index !== -1) {
60 parentValue.splice(index, 1); 76 parentValue.splice(index, 1);
61 parent.$emit('input', parentValue); 77 emit(parent, parentValue);
62 parent.$emit('change', parentValue);
63 } 78 }
64 } 79 }
65 } 80 },
81 setSizeWithUnit(size) {
82 this.set({
83 sizeWithUnit: addUnit(size)
84 });
85 },
66 } 86 }
67 }); 87 });
......
...@@ -6,10 +6,11 @@ ...@@ -6,10 +6,11 @@
6 <van-icon 6 <van-icon
7 wx:else 7 wx:else
8 name="success" 8 name="success"
9 size="0.8em"
9 class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}" 10 class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}"
10 style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}" 11 style="font-size: {{ sizeWithUnit }};{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
11 custom-class="icon-class" 12 custom-class="icon-class"
12 custom-style="line-height: 20px;" 13 custom-style="line-height: 1.25em;"
13 /> 14 />
14 </view> 15 </view>
15 <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel"> 16 <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel">
......
1 @import '../common/index.wxss';.van-checkbox{overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{display:inline-block;line-height:20px;vertical-align:middle}.van-checkbox__icon{display:block;font-size:14px;width:20px;height:20px;color:transparent;text-align:center;box-sizing:border-box;border:1px solid #e5e5e5;transition:.2s}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;border-color:#1989fa;background-color:#1989fa}.van-checkbox__icon--disabled{border-color:#c9c9c9;background-color:#eee}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c9c9c9}.van-checkbox__label{color:#333;margin-left:10px}.van-checkbox__label--left{float:left;margin:0 10px 0 0}.van-checkbox__label--disabled{color:#c9c9c9}.van-checkbox__label:empty{margin:0}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #e5e5e5;border:1px solid var(--checkbox-border-color,#e5e5e5);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component';
2 import { isObj } from '../common/utils';
3 import { BLUE, WHITE } from '../common/color';
4 function format(rate) {
5 return Math.min(Math.max(rate, 0), 100);
6 }
7 const PERIMETER = 2 * Math.PI;
8 const BEGIN_ANGLE = -Math.PI / 2;
9 const STEP = 1;
10 VantComponent({
11 props: {
12 text: String,
13 lineCap: {
14 type: String,
15 value: 'round'
16 },
17 value: {
18 type: Number,
19 value: 0,
20 observer: 'reRender'
21 },
22 speed: {
23 type: Number,
24 value: 50
25 },
26 size: {
27 type: Number,
28 value: 100,
29 observer: 'setStyle'
30 },
31 fill: String,
32 layerColor: {
33 type: String,
34 value: WHITE
35 },
36 color: {
37 type: [String, Object],
38 value: BLUE,
39 observer: 'setHoverColor'
40 },
41 strokeWidth: {
42 type: Number,
43 value: 4
44 },
45 clockwise: {
46 type: Boolean,
47 value: true
48 }
49 },
50 data: {
51 style: 'width: 100px; height: 100px;',
52 hoverColor: BLUE
53 },
54 methods: {
55 getContext() {
56 if (!this.ctx) {
57 this.ctx = wx.createCanvasContext('van-circle', this);
58 }
59 return this.ctx;
60 },
61 setHoverColor() {
62 const context = this.getContext();
63 const { color, size } = this.data;
64 let hoverColor = color;
65 if (isObj(color)) {
66 const LinearColor = context.createLinearGradient(size, 0, 0, 0);
67 Object.keys(color)
68 .sort((a, b) => parseFloat(a) - parseFloat(b))
69 .map(key => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
70 hoverColor = LinearColor;
71 }
72 this.setData({ hoverColor });
73 },
74 setStyle() {
75 const { size } = this.data;
76 const style = `width: ${size}px; height: ${size}px;`;
77 this.setData({ style });
78 },
79 presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
80 const { strokeWidth, lineCap, clockwise, size } = this.data;
81 const position = size / 2;
82 const radius = position - strokeWidth / 2;
83 context.setStrokeStyle(strokeStyle);
84 context.setLineWidth(strokeWidth);
85 context.setLineCap(lineCap);
86 context.beginPath();
87 context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
88 context.stroke();
89 if (fill) {
90 context.setFillStyle(fill);
91 context.fill();
92 }
93 },
94 renderLayerCircle(context) {
95 const { layerColor, fill } = this.data;
96 this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
97 },
98 renderHoverCircle(context, formatValue) {
99 const { clockwise, hoverColor } = this.data;
100 // 结束角度
101 const progress = PERIMETER * (formatValue / 100);
102 const endAngle = clockwise
103 ? BEGIN_ANGLE + progress
104 : 3 * Math.PI - (BEGIN_ANGLE + progress);
105 this.presetCanvas(context, hoverColor, BEGIN_ANGLE, endAngle);
106 },
107 drawCircle(currentValue) {
108 const context = this.getContext();
109 const { size } = this.data;
110 context.clearRect(0, 0, size, size);
111 this.renderLayerCircle(context);
112 const formatValue = format(currentValue);
113 if (formatValue !== 0) {
114 this.renderHoverCircle(context, formatValue);
115 }
116 context.draw();
117 },
118 reRender() {
119 // tofector 动画暂时没有想到好的解决方案
120 const { value, speed } = this.data;
121 if (speed <= 0 || speed > 1000) {
122 this.drawCircle(value);
123 return;
124 }
125 this.clearInterval();
126 this.currentValue = this.currentValue || 0;
127 this.interval = setInterval(() => {
128 if (this.currentValue !== value) {
129 if (this.currentValue < value) {
130 this.currentValue += STEP;
131 }
132 else {
133 this.currentValue -= STEP;
134 }
135 this.drawCircle(this.currentValue);
136 }
137 else {
138 this.clearInterval();
139 }
140 }, 1000 / speed);
141 },
142 clearInterval() {
143 if (this.interval) {
144 clearInterval(this.interval);
145 this.interval = null;
146 }
147 }
148 },
149 created() {
150 const { value } = this.data;
151 this.currentValue = value;
152 this.drawCircle(value);
153 },
154 destroyed() {
155 this.ctx = null;
156 this.clearInterval();
157 }
158 });
1 <view class="van-circle">
2 <canvas class="van-circle__canvas" style="{{ style }}" canvas-id="van-circle"></canvas>
3 <view wx:if="{{ !text }}" class="van-circle__text">
4 <slot></slot>
5 </view>
6 <cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
7 </view>
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}
...\ No newline at end of file ...\ No newline at end of file
...@@ -16,7 +16,7 @@ VantComponent({ ...@@ -16,7 +16,7 @@ VantComponent({
16 const padding = `${gutter / 2}px`; 16 const padding = `${gutter / 2}px`;
17 const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : ''; 17 const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
18 if (style !== this.data.style) { 18 if (style !== this.data.style) {
19 this.set({ style }); 19 this.setData({ style });
20 } 20 }
21 } 21 }
22 } 22 }
......
...@@ -16,6 +16,7 @@ VantComponent({ ...@@ -16,6 +16,7 @@ VantComponent({
16 icon: String, 16 icon: String,
17 label: String, 17 label: String,
18 disabled: Boolean, 18 disabled: Boolean,
19 clickable: Boolean,
19 border: { 20 border: {
20 type: Boolean, 21 type: Boolean,
21 value: true 22 value: true
...@@ -34,7 +35,11 @@ VantComponent({ ...@@ -34,7 +35,11 @@ VantComponent({
34 this.updateExpanded() 35 this.updateExpanded()
35 .then(nextTick) 36 .then(nextTick)
36 .then(() => { 37 .then(() => {
37 this.set({ transition: true }); 38 const data = { transition: true };
39 if (this.data.expanded) {
40 data.contentHeight = 'auto';
41 }
42 this.setData(data);
38 }); 43 });
39 }, 44 },
40 methods: { 45 methods: {
...@@ -66,11 +71,9 @@ VantComponent({ ...@@ -66,11 +71,9 @@ VantComponent({
66 contentHeight: height ? `${height}px` : 'auto' 71 contentHeight: height ? `${height}px` : 'auto'
67 }); 72 });
68 } 73 }
69 else { 74 return this.set({ contentHeight: `${height}px` })
70 return this.set({ contentHeight: `${height}px` }) 75 .then(nextTick)
71 .then(nextTick) 76 .then(() => this.set({ contentHeight: 0 }));
72 .then(() => this.set({ contentHeight: 0 }));
73 }
74 }); 77 });
75 }, 78 },
76 onClick() { 79 onClick() {
...@@ -84,7 +87,7 @@ VantComponent({ ...@@ -84,7 +87,7 @@ VantComponent({
84 }, 87 },
85 onTransitionEnd() { 88 onTransitionEnd() {
86 if (this.data.expanded) { 89 if (this.data.expanded) {
87 this.set({ 90 this.setData({
88 contentHeight: 'auto' 91 contentHeight: 'auto'
89 }); 92 });
90 } 93 }
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
5 title="{{ title }}" 5 title="{{ title }}"
6 title-class="title-class" 6 title-class="title-class"
7 icon="{{ icon }}" 7 icon="{{ icon }}"
8 is-link="{{ isLink }}"
9 value="{{ value }}" 8 value="{{ value }}"
10 label="{{ label }}" 9 label="{{ label }}"
10 is-link="{{ isLink }}"
11 clickable="{{ clickable }}"
11 border="{{ border && expanded }}" 12 border="{{ border && expanded }}"
12 class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}" 13 class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
13 right-icon-class="van-cell__right-icon" 14 right-icon-class="van-cell__right-icon"
......
1 @import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:.3s}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c9c9c9!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;font-size:13px;line-height:1.5;color:#999;background-color:#fff}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;transition:-webkit-transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s),-webkit-transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c8c9cc!important;color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important;background-color:var(--white,#fff)!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;padding:var(--collapse-item-content-padding,15px);color:#969799;color:var(--collapse-item-content-text-color,#969799);font-size:13px;font-size:var(--collapse-item-content-font-size,13px);line-height:1.5;line-height:var(--collapse-item-content-line-height,1.5);background-color:#fff;background-color:var(--collapse-item-content-background-color,#fff)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -5,6 +5,9 @@ VantComponent({ ...@@ -5,6 +5,9 @@ VantComponent({
5 type: 'descendant', 5 type: 'descendant',
6 linked(child) { 6 linked(child) {
7 this.children.push(child); 7 this.children.push(child);
8 },
9 unlinked(child) {
10 this.children = this.children.filter((item) => item !== child);
8 } 11 }
9 }, 12 },
10 props: { 13 props: {
......
1 export declare const RED = "#f44"; 1 export declare const RED = "#ee0a24";
2 export declare const BLUE = "#1989fa"; 2 export declare const BLUE = "#1989fa";
3 export declare const WHITE = "#fff";
3 export declare const GREEN = "#07c160"; 4 export declare const GREEN = "#07c160";
5 export declare const ORANGE = "#ff976a";
6 export declare const GRAY = "#323233";
7 export declare const GRAY_DARK = "#969799";
......
1 export const RED = '#f44'; 1 export const RED = '#ee0a24';
2 export const BLUE = '#1989fa'; 2 export const BLUE = '#1989fa';
3 export const WHITE = '#fff';
3 export const GREEN = '#07c160'; 4 export const GREEN = '#07c160';
5 export const ORANGE = '#ff976a';
6 export const GRAY = '#323233';
7 export const GRAY_DARK = '#969799';
......
1 declare function VantComponent<Data, Props, Watch, Methods, Computed>(vantOptions?: VantComponentOptions<Data, Props, Watch, Methods, Computed, CombinedComponentInstance<Data, Props, Watch, Methods, Computed>>): void; 1 import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
2 declare function VantComponent<Data, Props, Methods>(vantOptions?: VantComponentOptions<Data, Props, Methods, CombinedComponentInstance<Data, Props, Methods>>): void;
2 export { VantComponent }; 3 export { VantComponent };
......
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{content:"";display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
......
1 .van-clearfix:after{content:"";display:table;clear:both}
...\ No newline at end of file ...\ No newline at end of file
1 .van-clearfix:after{display:table;clear:both;content:""}
...\ No newline at end of file ...\ No newline at end of file
......
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
...\ No newline at end of file ...\ No newline at end of file
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
...\ No newline at end of file ...\ No newline at end of file
......
1 .van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
1 .van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
......
1 declare function isDef(value: any): boolean; 1 /// <reference types="miniprogram-api-typings" />
2 declare function isObj(x: any): boolean; 2 export declare function isDef(value: any): boolean;
3 declare function isNumber(value: any): boolean; 3 export declare function isObj(x: any): boolean;
4 declare function range(num: number, min: number, max: number): number; 4 export declare function isNumber(value: any): boolean;
5 export { isObj, isDef, isNumber, range }; 5 export declare function range(num: number, min: number, max: number): number;
6 export declare function nextTick(fn: Function): void;
7 export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSuccessCallbackResult;
8 export declare function addUnit(value?: string | number): string | undefined;
......
1 function isDef(value) { 1 export function isDef(value) {
2 return value !== undefined && value !== null; 2 return value !== undefined && value !== null;
3 } 3 }
4 function isObj(x) { 4 export function isObj(x) {
5 const type = typeof x; 5 const type = typeof x;
6 return x !== null && (type === 'object' || type === 'function'); 6 return x !== null && (type === 'object' || type === 'function');
7 } 7 }
8 function isNumber(value) { 8 export function isNumber(value) {
9 return /^\d+$/.test(value); 9 return /^\d+(\.\d+)?$/.test(value);
10 } 10 }
11 function range(num, min, max) { 11 export function range(num, min, max) {
12 return Math.min(Math.max(num, min), max); 12 return Math.min(Math.max(num, min), max);
13 } 13 }
14 export { isObj, isDef, isNumber, range }; 14 export function nextTick(fn) {
15 setTimeout(() => {
16 fn();
17 }, 1000 / 30);
18 }
19 let systemInfo = null;
20 export function getSystemInfoSync() {
21 if (systemInfo == null) {
22 systemInfo = wx.getSystemInfoSync();
23 }
24 return systemInfo;
25 }
26 export function addUnit(value) {
27 if (!isDef(value)) {
28 return undefined;
29 }
30 value = String(value);
31 return isNumber(value) ? `${value}px` : value;
32 }
......
1 import { VantComponent } from '../common/component';
2 import { isSameSecond, parseFormat, parseTimeData } from './utils';
3 function simpleTick(fn) {
4 return setTimeout(fn, 30);
5 }
6 VantComponent({
7 props: {
8 useSlot: Boolean,
9 millisecond: Boolean,
10 time: {
11 type: Number,
12 observer: 'reset'
13 },
14 format: {
15 type: String,
16 value: 'HH:mm:ss'
17 },
18 autoStart: {
19 type: Boolean,
20 value: true
21 }
22 },
23 data: {
24 timeData: parseTimeData(0),
25 formattedTime: '0'
26 },
27 destroyed() {
28 clearTimeout(this.tid);
29 this.tid = null;
30 },
31 methods: {
32 // 开始
33 start() {
34 if (this.counting) {
35 return;
36 }
37 this.counting = true;
38 this.endTime = Date.now() + this.remain;
39 this.tick();
40 },
41 // 暂停
42 pause() {
43 this.counting = false;
44 clearTimeout(this.tid);
45 },
46 // 重置
47 reset() {
48 this.pause();
49 this.remain = this.data.time;
50 this.setRemain(this.remain);
51 if (this.data.autoStart) {
52 this.start();
53 }
54 },
55 tick() {
56 if (this.data.millisecond) {
57 this.microTick();
58 }
59 else {
60 this.macroTick();
61 }
62 },
63 microTick() {
64 this.tid = simpleTick(() => {
65 this.setRemain(this.getRemain());
66 if (this.remain !== 0) {
67 this.microTick();
68 }
69 });
70 },
71 macroTick() {
72 this.tid = simpleTick(() => {
73 const remain = this.getRemain();
74 if (!isSameSecond(remain, this.remain) || remain === 0) {
75 this.setRemain(remain);
76 }
77 if (this.remain !== 0) {
78 this.macroTick();
79 }
80 });
81 },
82 getRemain() {
83 return Math.max(this.endTime - Date.now(), 0);
84 },
85 setRemain(remain) {
86 this.remain = remain;
87 const timeData = parseTimeData(remain);
88 if (this.data.useSlot) {
89 this.$emit('change', timeData);
90 }
91 this.setData({
92 formattedTime: parseFormat(this.data.format, timeData)
93 });
94 if (remain === 0) {
95 this.pause();
96 this.$emit('finish');
97 }
98 }
99 }
100 });
1 <view class="van-count-down">
2 <slot wx:if="{{ useSlot }}"/>
3 <block wx:else>{{ formattedTime }}</block>
4 </view>
1 @import '../common/index.wxss';.van-count-down{color:#323233;color:var(--count-down-text-color,#323233);font-size:14px;font-size:var(--count-down-font-size,14px);line-height:20px;line-height:var(--count-down-line-height,20px)}
...\ No newline at end of file ...\ No newline at end of file
1 export declare type TimeData = {
2 days: number;
3 hours: number;
4 minutes: number;
5 seconds: number;
6 milliseconds: number;
7 };
8 export declare function parseTimeData(time: number): TimeData;
9 export declare function parseFormat(format: string, timeData: TimeData): string;
10 export declare function isSameSecond(time1: number, time2: number): boolean;
1 function padZero(num, targetLength = 2) {
2 let str = num + '';
3 while (str.length < targetLength) {
4 str = '0' + str;
5 }
6 return str;
7 }
8 const SECOND = 1000;
9 const MINUTE = 60 * SECOND;
10 const HOUR = 60 * MINUTE;
11 const DAY = 24 * HOUR;
12 export function parseTimeData(time) {
13 const days = Math.floor(time / DAY);
14 const hours = Math.floor((time % DAY) / HOUR);
15 const minutes = Math.floor((time % HOUR) / MINUTE);
16 const seconds = Math.floor((time % MINUTE) / SECOND);
17 const milliseconds = Math.floor(time % SECOND);
18 return {
19 days,
20 hours,
21 minutes,
22 seconds,
23 milliseconds
24 };
25 }
26 export function parseFormat(format, timeData) {
27 const { days } = timeData;
28 let { hours, minutes, seconds, milliseconds } = timeData;
29 if (format.indexOf('DD') === -1) {
30 hours += days * 24;
31 }
32 else {
33 format = format.replace('DD', padZero(days));
34 }
35 if (format.indexOf('HH') === -1) {
36 minutes += hours * 60;
37 }
38 else {
39 format = format.replace('HH', padZero(hours));
40 }
41 if (format.indexOf('mm') === -1) {
42 seconds += minutes * 60;
43 }
44 else {
45 format = format.replace('mm', padZero(minutes));
46 }
47 if (format.indexOf('ss') === -1) {
48 milliseconds += seconds * 1000;
49 }
50 else {
51 format = format.replace('ss', padZero(seconds));
52 }
53 return format.replace('SSS', padZero(milliseconds, 3));
54 }
55 export function isSameSecond(time1, time2) {
56 return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
57 }
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { isDef } from '../common/utils'; 2 import { isDef } from '../common/utils';
3 import { pickerProps } from '../picker/shared';
3 const currentYear = new Date().getFullYear(); 4 const currentYear = new Date().getFullYear();
4 function isValidDate(date) { 5 function isValidDate(date) {
5 return isDef(date) && !isNaN(new Date(date).getTime()); 6 return isDef(date) && !isNaN(new Date(date).getTime());
...@@ -12,7 +13,7 @@ function padZero(val) { ...@@ -12,7 +13,7 @@ function padZero(val) {
12 } 13 }
13 function times(n, iteratee) { 14 function times(n, iteratee) {
14 let index = -1; 15 let index = -1;
15 const result = Array(n); 16 const result = Array(n < 0 ? 0 : n);
16 while (++index < n) { 17 while (++index < n) {
17 result[index] = iteratee(index); 18 result[index] = iteratee(index);
18 } 19 }
...@@ -29,100 +30,95 @@ function getTrueValue(formattedValue) { ...@@ -29,100 +30,95 @@ function getTrueValue(formattedValue) {
29 function getMonthEndDay(year, month) { 30 function getMonthEndDay(year, month) {
30 return 32 - new Date(year, month - 1, 32).getDate(); 31 return 32 - new Date(year, month - 1, 32).getDate();
31 } 32 }
33 const defaultFormatter = (_, value) => value;
32 VantComponent({ 34 VantComponent({
33 props: { 35 classes: ['active-class', 'toolbar-class', 'column-class'],
34 value: null, 36 props: Object.assign(Object.assign({}, pickerProps), { value: null, filter: null, type: {
35 title: String,
36 loading: Boolean,
37 itemHeight: {
38 type: Number,
39 value: 44
40 },
41 visibleItemCount: {
42 type: Number,
43 value: 5
44 },
45 confirmButtonText: {
46 type: String,
47 value: '确认'
48 },
49 cancelButtonText: {
50 type: String,
51 value: '取消'
52 },
53 type: {
54 type: String, 37 type: String,
55 value: 'datetime' 38 value: 'datetime'
56 }, 39 }, showToolbar: {
57 showToolbar: {
58 type: Boolean, 40 type: Boolean,
59 value: true 41 value: true
60 }, 42 }, formatter: {
61 minDate: { 43 type: null,
44 value: defaultFormatter
45 }, minDate: {
62 type: Number, 46 type: Number,
63 value: new Date(currentYear - 10, 0, 1).getTime() 47 value: new Date(currentYear - 10, 0, 1).getTime()
64 }, 48 }, maxDate: {
65 maxDate: {
66 type: Number, 49 type: Number,
67 value: new Date(currentYear + 10, 11, 31).getTime() 50 value: new Date(currentYear + 10, 11, 31).getTime()
68 }, 51 }, minHour: {
69 minHour: {
70 type: Number, 52 type: Number,
71 value: 0 53 value: 0
72 }, 54 }, maxHour: {
73 maxHour: {
74 type: Number, 55 type: Number,
75 value: 23 56 value: 23
76 }, 57 }, minMinute: {
77 minMinute: {
78 type: Number, 58 type: Number,
79 value: 0 59 value: 0
80 }, 60 }, maxMinute: {
81 maxMinute: {
82 type: Number, 61 type: Number,
83 value: 59 62 value: 59
84 } 63 } }),
85 },
86 data: { 64 data: {
87 innerValue: Date.now(), 65 innerValue: Date.now(),
88 columns: [] 66 columns: []
89 }, 67 },
90 watch: { 68 watch: {
91 value(val) { 69 value: 'updateValue',
70 type: 'updateValue',
71 minDate: 'updateValue',
72 maxDate: 'updateValue',
73 minHour: 'updateValue',
74 maxHour: 'updateValue',
75 minMinute: 'updateValue',
76 maxMinute: 'updateValue'
77 },
78 methods: {
79 updateValue() {
92 const { data } = this; 80 const { data } = this;
93 val = this.correctValue(val); 81 const val = this.correctValue(this.data.value);
94 const isEqual = val === data.innerValue; 82 const isEqual = val === data.innerValue;
95 if (!isEqual) { 83 if (!isEqual) {
96 this.updateColumnValue(val).then(() => { 84 this.updateColumnValue(val).then(() => {
97 this.$emit('input', val); 85 this.$emit('input', val);
98 }); 86 });
99 } 87 }
88 else {
89 this.updateColumns();
90 }
100 }, 91 },
101 type: 'updateColumns',
102 minHour: 'updateColumns',
103 maxHour: 'updateColumns',
104 minMinute: 'updateColumns',
105 maxMinute: 'updateColumns'
106 },
107 methods: {
108 getPicker() { 92 getPicker() {
109 if (this.picker == null) { 93 if (this.picker == null) {
110 const picker = this.picker = this.selectComponent('.van-datetime-picker'); 94 this.picker = this.selectComponent('.van-datetime-picker');
95 const { picker } = this;
111 const { setColumnValues } = picker; 96 const { setColumnValues } = picker;
112 picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]); 97 picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
113 } 98 }
114 return this.picker; 99 return this.picker;
115 }, 100 },
116 updateColumns() { 101 updateColumns() {
117 const results = this.getRanges().map(({ type, range }, index) => { 102 const { formatter = defaultFormatter } = this.data;
118 const values = times(range[1] - range[0] + 1, index => { 103 const results = this.getOriginColumns().map(column => ({
104 values: column.values.map(value => formatter(column.type, value))
105 }));
106 return this.set({ columns: results });
107 },
108 getOriginColumns() {
109 const { filter } = this.data;
110 const results = this.getRanges().map(({ type, range }) => {
111 let values = times(range[1] - range[0] + 1, index => {
119 let value = range[0] + index; 112 let value = range[0] + index;
120 value = type === 'year' ? `${value}` : padZero(value); 113 value = type === 'year' ? `${value}` : padZero(value);
121 return value; 114 return value;
122 }); 115 });
123 return { values }; 116 if (filter) {
117 values = filter(type, values);
118 }
119 return { type, values };
124 }); 120 });
125 return this.set({ columns: results }); 121 return results;
126 }, 122 },
127 getRanges() { 123 getRanges() {
128 const { data } = this; 124 const { data } = this;
...@@ -237,7 +233,7 @@ VantComponent({ ...@@ -237,7 +233,7 @@ VantComponent({
237 const picker = this.getPicker(); 233 const picker = this.getPicker();
238 if (data.type === 'time') { 234 if (data.type === 'time') {
239 const indexes = picker.getIndexes(); 235 const indexes = picker.getIndexes();
240 value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`; 236 value = `${+data.columns[0].values[indexes[0]]}:${+data.columns[1].values[indexes[1]]}`;
241 } 237 }
242 else { 238 else {
243 const values = picker.getValues(); 239 const values = picker.getValues();
...@@ -265,20 +261,26 @@ VantComponent({ ...@@ -265,20 +261,26 @@ VantComponent({
265 }, 261 },
266 updateColumnValue(value) { 262 updateColumnValue(value) {
267 let values = []; 263 let values = [];
268 const { data } = this; 264 const { type, formatter = defaultFormatter } = this.data;
269 const picker = this.getPicker(); 265 const picker = this.getPicker();
270 if (data.type === 'time') { 266 if (type === 'time') {
271 const pair = value.split(':'); 267 const pair = value.split(':');
272 values = [pair[0], pair[1]]; 268 values = [
269 formatter('hour', pair[0]),
270 formatter('minute', pair[1])
271 ];
273 } 272 }
274 else { 273 else {
275 const date = new Date(value); 274 const date = new Date(value);
276 values = [`${date.getFullYear()}`, padZero(date.getMonth() + 1)]; 275 values = [
277 if (data.type === 'date') { 276 formatter('year', `${date.getFullYear()}`),
278 values.push(padZero(date.getDate())); 277 formatter('month', padZero(date.getMonth() + 1))
278 ];
279 if (type === 'date') {
280 values.push(formatter('day', padZero(date.getDate())));
279 } 281 }
280 if (data.type === 'datetime') { 282 if (type === 'datetime') {
281 values.push(padZero(date.getDate()), padZero(date.getHours()), padZero(date.getMinutes())); 283 values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes())));
282 } 284 }
283 } 285 }
284 return this.set({ innerValue: value }) 286 return this.set({ innerValue: value })
......
1 <van-picker 1 <van-picker
2 class="van-datetime-picker" 2 class="van-datetime-picker"
3 active-class="active-class"
4 toolbar-class="toolbar-class"
5 column-class="column-class"
3 title="{{ title }}" 6 title="{{ title }}"
4 columns="{{ columns }}" 7 columns="{{ columns }}"
5 item-height="{{ itemHeight }}" 8 item-height="{{ itemHeight }}"
......
1 /// <reference types="miniprogram-api-typings" />
2 import { Weapp } from './weapp';
3 declare type RecordToAny<T> = {
4 [K in keyof T]: any;
5 };
6 export declare type CombinedComponentInstance<Data, Props, Methods> = Methods & WechatMiniprogram.Component.TrivialInstance & Weapp.FormField & {
7 data: Data & RecordToAny<Props>;
8 };
9 export interface VantComponentOptions<Data, Props, Methods, Instance> {
10 data?: Data;
11 field?: boolean;
12 classes?: string[];
13 mixins?: string[];
14 props?: Props & Weapp.PropertyOption;
15 watch?: Weapp.WatchOption<Instance>;
16 relation?: Weapp.RelationOption<Instance> & {
17 name: string;
18 };
19 relations?: {
20 [componentName: string]: Weapp.RelationOption<Instance>;
21 };
22 methods?: Methods & Weapp.MethodOption<Instance>;
23 beforeCreate?: (this: Instance) => void;
24 created?: (this: Instance) => void;
25 mounted?: (this: Instance) => void;
26 destroyed?: (this: Instance) => void;
27 }
28 export {};
1 /// <reference types="miniprogram-api-typings" />
2 export declare namespace Weapp {
3 export interface FormField {
4 data: {
5 name: string;
6 value: any;
7 };
8 }
9 interface Target {
10 id: string;
11 tagName: string;
12 dataset: {
13 [key: string]: any;
14 };
15 }
16 export interface Event {
17 /**
18 * 代表事件的类型。
19 */
20 type: string;
21 /**
22 * 页面打开到触发事件所经过的毫秒数。
23 */
24 timeStamp: number;
25 /**
26 * 触发事件的源组件。
27 */
28 target: Target;
29 /**
30 * 事件绑定的当前组件。
31 */
32 currentTarget: Target;
33 /**
34 * 额外的信息
35 */
36 detail: any;
37 }
38 interface Touch {
39 /**
40 * 触摸点的标识符
41 */
42 identifier: number;
43 /**
44 * 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
45 */
46 pageX: number;
47 /**
48 * 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
49 */
50 pageY: number;
51 /**
52 * 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
53 */
54 clientX: number;
55 /**
56 * 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
57 */
58 clientY: number;
59 }
60 export interface TouchEvent extends Event {
61 touches: Array<Touch>;
62 changedTouches: Array<Touch>;
63 }
64 /**
65 * relation定义,miniprogram-api-typings缺少this定义
66 */
67 export interface RelationOption<Instance> {
68 /** 目标组件的相对关系 */
69 type: 'parent' | 'child' | 'ancestor' | 'descendant';
70 /** 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后 */
71 linked?(this: Instance, target: WechatMiniprogram.Component.TrivialInstance): void;
72 /** 关系生命周期函数,当关系在页面节点树中发生改变时触发,触发时机在组件moved生命周期之后 */
73 linkChanged?(this: Instance, target: WechatMiniprogram.Component.TrivialInstance): void;
74 /** 关系生命周期函数,当关系脱离页面节点树时触发,触发时机在组件detached生命周期之后 */
75 unlinked?(this: Instance, target: WechatMiniprogram.Component.TrivialInstance): void;
76 /** 如果这一项被设置,则它表示关联的目标节点所应具有的behavior,所有拥有这一behavior的组件节点都会被关联 */
77 target?: string;
78 }
79 /**
80 * obverser定义,miniprogram-api-typings缺少this定义
81 */
82 type Observer<Instance, T> = (this: Instance, newVal: T, oldVal: T, changedPath: Array<string | number>) => void;
83 /**
84 * watch定义
85 */
86 export interface WatchOption<Instance> {
87 [name: string]: string | Observer<Instance, any>;
88 }
89 /**
90 * methods定义,miniprogram-api-typings缺少this定义
91 */
92 export interface MethodOption<Instance> {
93 [name: string]: (this: Instance, ...args: any[]) => any;
94 }
95 export interface ComputedOption<Instance> {
96 [name: string]: (this: Instance) => any;
97 }
98 type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | FunctionConstructor | null;
99 export interface PropertyOption {
100 [name: string]: PropertyType | PropertyType[] | {
101 /** 属性类型 */
102 type: PropertyType | PropertyType[];
103 /** 属性初始值 */
104 value?: any;
105 /** 属性值被更改时的响应函数 */
106 observer?: string | Observer<WechatMiniprogram.Component.TrivialInstance, any>;
107 /** 属性的类型(可以指定多个) */
108 optionalTypes?: PropertyType[];
109 };
110 }
111 export {};
112 }
1 /// <reference types="miniprogram-api-typings" />
1 declare type DialogAction = 'confirm' | 'cancel'; 2 declare type DialogAction = 'confirm' | 'cancel';
2 declare type DialogOptions = { 3 declare type DialogOptions = {
3 lang?: string; 4 lang?: string;
4 show?: boolean; 5 show?: boolean;
5 title?: string; 6 title?: string;
7 width?: string | number;
6 zIndex?: number; 8 zIndex?: number;
7 context?: any; 9 context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
8 message?: string; 10 message?: string;
9 overlay?: boolean; 11 overlay?: boolean;
10 selector?: string; 12 selector?: string;
11 ariaLabel?: string; 13 ariaLabel?: string;
14 className?: string;
15 customStyle?: string;
12 transition?: string; 16 transition?: string;
13 asyncClose?: boolean; 17 asyncClose?: boolean;
14 businessId?: number; 18 businessId?: number;
15 sessionFrom?: string; 19 sessionFrom?: string;
20 overlayStyle?: string;
16 appParameter?: string; 21 appParameter?: string;
17 messageAlign?: string; 22 messageAlign?: string;
18 sendMessageImg?: string; 23 sendMessageImg?: string;
......
...@@ -4,13 +4,14 @@ function getContext() { ...@@ -4,13 +4,14 @@ function getContext() {
4 return pages[pages.length - 1]; 4 return pages[pages.length - 1];
5 } 5 }
6 const Dialog = options => { 6 const Dialog = options => {
7 options = Object.assign({}, Dialog.currentOptions, options); 7 options = Object.assign(Object.assign({}, Dialog.currentOptions), options);
8 return new Promise((resolve, reject) => { 8 return new Promise((resolve, reject) => {
9 const context = options.context || getContext(); 9 const context = options.context || getContext();
10 const dialog = context.selectComponent(options.selector); 10 const dialog = context.selectComponent(options.selector);
11 delete options.context;
11 delete options.selector; 12 delete options.selector;
12 if (dialog) { 13 if (dialog) {
13 dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options)); 14 dialog.setData(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
14 queue.push(dialog); 15 queue.push(dialog);
15 } 16 }
16 else { 17 else {
...@@ -21,13 +22,17 @@ const Dialog = options => { ...@@ -21,13 +22,17 @@ const Dialog = options => {
21 Dialog.defaultOptions = { 22 Dialog.defaultOptions = {
22 show: true, 23 show: true,
23 title: '', 24 title: '',
25 width: null,
24 message: '', 26 message: '',
25 zIndex: 100, 27 zIndex: 100,
26 overlay: true, 28 overlay: true,
29 selector: '#van-dialog',
30 className: '',
27 asyncClose: false, 31 asyncClose: false,
28 messageAlign: '',
29 transition: 'scale', 32 transition: 'scale',
30 selector: '#van-dialog', 33 customStyle: '',
34 messageAlign: '',
35 overlayStyle: '',
31 confirmButtonText: '确认', 36 confirmButtonText: '确认',
32 cancelButtonText: '取消', 37 cancelButtonText: '取消',
33 showConfirmButton: true, 38 showConfirmButton: true,
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { button } from '../mixins/button'; 2 import { button } from '../mixins/button';
3 import { openType } from '../mixins/open-type'; 3 import { openType } from '../mixins/open-type';
4 import { addUnit } from '../common/utils';
5 import { GRAY, BLUE } from '../common/color';
4 VantComponent({ 6 VantComponent({
5 mixins: [button, openType], 7 mixins: [button, openType],
6 props: { 8 props: {
...@@ -8,11 +10,19 @@ VantComponent({ ...@@ -8,11 +10,19 @@ VantComponent({
8 title: String, 10 title: String,
9 message: String, 11 message: String,
10 useSlot: Boolean, 12 useSlot: Boolean,
13 className: String,
14 customStyle: String,
11 asyncClose: Boolean, 15 asyncClose: Boolean,
12 messageAlign: String, 16 messageAlign: String,
17 overlayStyle: String,
18 useTitleSlot: Boolean,
13 showCancelButton: Boolean, 19 showCancelButton: Boolean,
14 closeOnClickOverlay: Boolean, 20 closeOnClickOverlay: Boolean,
15 confirmButtonOpenType: String, 21 confirmButtonOpenType: String,
22 width: {
23 type: null,
24 observer: 'setWidthWithUnit'
25 },
16 zIndex: { 26 zIndex: {
17 type: Number, 27 type: Number,
18 value: 2000 28 value: 2000
...@@ -25,6 +35,14 @@ VantComponent({ ...@@ -25,6 +35,14 @@ VantComponent({
25 type: String, 35 type: String,
26 value: '取消' 36 value: '取消'
27 }, 37 },
38 confirmButtonColor: {
39 type: String,
40 value: BLUE
41 },
42 cancelButtonColor: {
43 type: String,
44 value: GRAY
45 },
28 showConfirmButton: { 46 showConfirmButton: {
29 type: Boolean, 47 type: Boolean,
30 value: true 48 value: true
...@@ -61,19 +79,19 @@ VantComponent({ ...@@ -61,19 +79,19 @@ VantComponent({
61 }, 79 },
62 handleAction(action) { 80 handleAction(action) {
63 if (this.data.asyncClose) { 81 if (this.data.asyncClose) {
64 this.set({ 82 this.setData({
65 [`loading.${action}`]: true 83 [`loading.${action}`]: true
66 }); 84 });
67 } 85 }
68 this.onClose(action); 86 this.onClose(action);
69 }, 87 },
70 close() { 88 close() {
71 this.set({ 89 this.setData({
72 show: false 90 show: false
73 }); 91 });
74 }, 92 },
75 stopLoading() { 93 stopLoading() {
76 this.set({ 94 this.setData({
77 loading: { 95 loading: {
78 confirm: false, 96 confirm: false,
79 cancel: false 97 cancel: false
...@@ -85,12 +103,17 @@ VantComponent({ ...@@ -85,12 +103,17 @@ VantComponent({
85 this.close(); 103 this.close();
86 } 104 }
87 this.$emit('close', action); 105 this.$emit('close', action);
88 //把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading 106 // 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
89 this.$emit(action, { dialog: this }); 107 this.$emit(action, { dialog: this });
90 const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel']; 108 const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel'];
91 if (callback) { 109 if (callback) {
92 callback(this); 110 callback(this);
93 } 111 }
112 },
113 setWidthWithUnit(val) {
114 this.setData({
115 widthWithUnit: addUnit(val)
116 });
94 } 117 }
95 } 118 }
96 }); 119 });
......
...@@ -2,16 +2,19 @@ ...@@ -2,16 +2,19 @@
2 show="{{ show }}" 2 show="{{ show }}"
3 z-index="{{ zIndex }}" 3 z-index="{{ zIndex }}"
4 overlay="{{ overlay }}" 4 overlay="{{ overlay }}"
5 custom-class="van-dialog"
6 transition="{{ transition }}" 5 transition="{{ transition }}"
6 custom-class="van-dialog {{ className }}"
7 custom-style="{{ widthWithUnit ? 'width: ' + widthWithUnit + ';' : '' }}{{ customStyle }}"
8 overlay-style="{{ overlayStyle }}"
7 close-on-click-overlay="{{ closeOnClickOverlay }}" 9 close-on-click-overlay="{{ closeOnClickOverlay }}"
8 bind:close="onClickOverlay" 10 bind:close="onClickOverlay"
9 > 11 >
10 <view 12 <view
11 wx:if="{{ title }}" 13 wx:if="{{ title || useTitleSlot }}"
12 class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}" 14 class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
13 > 15 >
14 {{ title }} 16 <slot wx:if="{{ useTitleSlot }}" name="title" />
17 <block wx:elif="{{ title }}"> {{ title }}</block>
15 </view> 18 </view>
16 19
17 <slot wx:if="{{ useSlot }}" /> 20 <slot wx:if="{{ useSlot }}" />
...@@ -19,7 +22,7 @@ ...@@ -19,7 +22,7 @@
19 wx:elif="{{ message }}" 22 wx:elif="{{ message }}"
20 class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}" 23 class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}"
21 > 24 >
22 <text>{{ message }}</text> 25 <text class="van-dialog__message-text">{{ message }}</text>
23 </view> 26 </view>
24 27
25 <view class="van-hairline--top van-dialog__footer"> 28 <view class="van-hairline--top van-dialog__footer">
...@@ -29,6 +32,7 @@ ...@@ -29,6 +32,7 @@
29 loading="{{ loading.cancel }}" 32 loading="{{ loading.cancel }}"
30 class="van-dialog__button van-hairline--right" 33 class="van-dialog__button van-hairline--right"
31 custom-class="van-dialog__cancel" 34 custom-class="van-dialog__cancel"
35 custom-style="color: {{ cancelButtonColor }}"
32 bind:click="onCancel" 36 bind:click="onCancel"
33 > 37 >
34 {{ cancelButtonText }} 38 {{ cancelButtonText }}
...@@ -39,6 +43,7 @@ ...@@ -39,6 +43,7 @@
39 class="van-dialog__button" 43 class="van-dialog__button"
40 loading="{{ loading.confirm }}" 44 loading="{{ loading.confirm }}"
41 custom-class="van-dialog__confirm" 45 custom-class="van-dialog__confirm"
46 custom-style="color: {{ confirmButtonColor }}"
42 47
43 open-type="{{ confirmButtonOpenType }}" 48 open-type="{{ confirmButtonOpenType }}"
44 lang="{{ lang }}" 49 lang="{{ lang }}"
......
1 @import '../common/index.wxss';.van-dialog{width:85%;overflow:hidden;font-size:16px;background-color:#fff;border-radius:4px}.van-dialog__header{padding-top:25px;font-weight:500;text-align:center}.van-dialog__header--isolated{padding:25px 0}.van-dialog__message{max-height:60vh;padding:25px;overflow-y:auto;font-size:14px;line-height:1.5;text-align:center;-webkit-overflow-scrolling:touch}.van-dialog__message--has-title{padding-top:12px;color:#7d7e80}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog__confirm{color:#1989fa!important}.van-dialog-bounce-enter{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-dialog{top:45%!important;overflow:hidden;width:320px;width:var(--dialog-width,320px);font-size:16px;font-size:var(--dialog-font-size,16px);border-radius:16px;border-radius:var(--dialog-border-radius,16px);background-color:#fff;background-color:var(--dialog-background-color,#fff)}@media (max-width:321px){.van-dialog{width:90%;width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{text-align:center;padding-top:24px;padding-top:var(--dialog-header-padding-top,24px);font-weight:500;font-weight:var(--dialog-header-font-weight,500);line-height:24px;line-height:var(--dialog-header-line-height,24px)}.van-dialog__header--isolated{padding:24px 0;padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{overflow-y:auto;text-align:center;-webkit-overflow-scrolling:touch;font-size:14px;font-size:var(--dialog-message-font-size,14px);line-height:20px;line-height:var(--dialog-message-line-height,20px);max-height:60vh;max-height:var(--dialog-message-max-height,60vh);padding:24px;padding:var(--dialog-message-padding,24px)}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--has-title{padding-top:12px;padding-top:var(--dialog-has-title-message-padding-top,12px);color:#7d7e80;color:var(--dialog-has-title-message-text-color,#7d7e80)}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-dialog-bounce-leave-active{-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9);opacity:0}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 dashed: {
5 type: Boolean,
6 value: false
7 },
8 hairline: {
9 type: Boolean,
10 value: false
11 },
12 contentPosition: {
13 type: String,
14 value: ''
15 },
16 fontSize: {
17 type: Number,
18 value: ''
19 },
20 borderColor: {
21 type: String,
22 value: ''
23 },
24 textColor: {
25 type: String,
26 value: ''
27 },
28 customStyle: {
29 type: String,
30 value: ''
31 }
32 }
33 });
1 {
2 "component": true,
3 "usingComponents": {}
4 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('divider', [{dashed, hairline}, contentPosition]) }}"
5 style="{{ borderColor ? 'border-color: ' + borderColor + ';' : '' }}{{ textColor ? 'color: ' + textColor + ';' : '' }} {{ fontSize ? 'font-size: ' + fontSize + 'px;' : '' }} {{ customStyle }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-divider{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin:16px 0;margin:var(--divider-margin,16px 0);color:#969799;color:var(--divider-text-color,#969799);font-size:14px;font-size:var(--divider-font-size,14px);line-height:24px;line-height:var(--divider-line-height,24px);border:0 solid #ebedf0;border-color:var(--divider-border-color,#ebedf0)}.van-divider:after,.van-divider:before{display:block;-webkit-flex:1;flex:1;box-sizing:border-box;height:1px;border-color:inherit;border-style:inherit;border-width:1px 0 0}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:16px;margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:16px;margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:10%;max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:10%;max-width:var(--divider-content-right-width,10%)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'dropdown-menu',
6 type: 'ancestor',
7 linked(target) {
8 this.parent = target;
9 },
10 unlinked() {
11 this.parent = null;
12 }
13 },
14 props: {
15 value: null,
16 title: String,
17 disabled: Boolean,
18 titleClass: String,
19 options: {
20 type: Array,
21 value: []
22 }
23 },
24 data: {
25 transition: true,
26 showPopup: false,
27 showWrapper: false,
28 displayTitle: ''
29 },
30 created() {
31 this.setData({ displayTitle: this.computedDisplayTitle(this.data.value) });
32 },
33 methods: {
34 computedDisplayTitle(curValue) {
35 const { title, options } = this.data;
36 if (title) {
37 return title;
38 }
39 const match = options.filter(option => option.value === curValue);
40 const displayTitle = match.length ? match[0].text : '';
41 return displayTitle;
42 },
43 onClickOverlay() {
44 this.toggle();
45 this.$emit('close');
46 },
47 onOptionTap(event) {
48 let { value, displayTitle } = this.data;
49 const { option } = event.currentTarget.dataset;
50 const { value: optionValue } = option;
51 if (optionValue !== value) {
52 value = optionValue;
53 displayTitle = this.computedDisplayTitle(optionValue);
54 this.$emit('change', optionValue);
55 }
56 this.setData({ showPopup: false, value, displayTitle });
57 const time = this.data.duration || 0;
58 setTimeout(() => {
59 this.setData({ showWrapper: false });
60 }, time);
61 // parent 中的 itemListData 是 children 上的数据的集合
62 // 数据的更新由 children 各自维护,但是模板的更新需要额外触发 parent 的 setData
63 this.parent.setData({ itemListData: this.parent.data.itemListData });
64 },
65 toggle() {
66 const { childIndex } = this.data;
67 this.parent.toggleItem(childIndex);
68 }
69 }
70 });
1 { 1 {
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-popup": "../popup/index",
4 "van-cell": "../cell/index", 5 "van-cell": "../cell/index",
5 "van-switch": "../switch/index" 6 "van-icon": "../icon/index"
6 } 7 }
7 } 8 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 wx:if="{{ showWrapper }}"
5 class="{{ utils.bem('dropdown-item', direction) }}"
6 style="{{ wrapperStyle }}"
7 >
8 <van-popup
9 show="{{ showPopup }}"
10 custom-style="position: absolute;"
11 overlay-style="position: absolute;"
12 overlay="{{ overlay }}"
13 position="{{ direction === 'down' ? 'top' : 'bottom' }}"
14 duration="{{ transition ? duration : 0 }}"
15 close-on-click-overlay="{{ closeOnClickOverlay }}"
16 bind:close="onClickOverlay"
17 >
18 <van-cell
19 wx:for="{{ options }}"
20 wx:key="{{ item.value }}"
21 data-option="{{ item }}"
22 class="{{ utils.bem('dropdown-item__option', { active: item.value === value } ) }}"
23 clickable
24 icon="{{ item.icon }}"
25 bind:tap="onOptionTap"
26 >
27 <view
28 slot="title"
29 class="van-dropdown-item__title"
30 style="{{ item.value === value ? 'color:' + activeColor : '' }}"
31 >
32 {{ item.text }}
33 </view>
34 <van-icon
35 wx:if="{{ item.value === value }}"
36 name="success"
37 class="van-dropdown-item__icon"
38 color="{{ activeColor }}"
39 />
40 </van-cell>
41
42 <slot />
43 </van-popup>
44 </view>
1 @import '../common/index.wxss';.van-dropdown-item{position:fixed;right:0;left:0;overflow:hidden}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:#1989fa;color:var(--dropdown-menu-option-active-color,#1989fa)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { addUnit } from '../common/utils';
3 let ARRAY = [];
4 VantComponent({
5 field: true,
6 relation: {
7 name: 'dropdown-item',
8 type: 'descendant',
9 linked(target) {
10 this.children = this.children || [];
11 // 透传 props 给 dropdown-item
12 const { overlay, duration, activeColor, closeOnClickOverlay, direction } = this.data;
13 this.updateChildData(target, {
14 overlay,
15 duration,
16 activeColor,
17 closeOnClickOverlay,
18 direction,
19 childIndex: this.children.length
20 });
21 this.children.push(target);
22 // 收集 dorpdown-item 的 data 挂在 data 上
23 target &&
24 this.setData({
25 itemListData: this.data.itemListData.concat([target.data])
26 });
27 },
28 unlinked(target) {
29 this.children = this.children.filter((child) => child !== target);
30 }
31 },
32 props: {
33 activeColor: String,
34 overlay: {
35 type: Boolean,
36 value: true
37 },
38 zIndex: {
39 type: Number,
40 value: 10
41 },
42 duration: {
43 type: Number,
44 value: 200
45 },
46 direction: {
47 type: String,
48 value: 'down'
49 },
50 closeOnClickOverlay: {
51 type: Boolean,
52 value: true
53 },
54 closeOnClickOutside: {
55 type: Boolean,
56 value: true
57 }
58 },
59 data: {
60 itemListData: []
61 },
62 created() {
63 ARRAY.push(this);
64 },
65 destroyed() {
66 ARRAY = ARRAY.filter(item => item !== this);
67 },
68 methods: {
69 updateChildData(childItem, newData, needRefreshList = false) {
70 childItem.setData(newData);
71 if (needRefreshList) {
72 // dropdown-item data 更新,涉及到 title 的展示,触发模板更新
73 this.setData({ itemListData: this.data.itemListData });
74 }
75 },
76 toggleItem(active) {
77 this.children.forEach((item, index) => {
78 const { showPopup } = item.data;
79 if (index === active) {
80 this.toggleChildItem(item);
81 }
82 else if (showPopup) {
83 this.toggleChildItem(item, false, { immediate: true });
84 }
85 });
86 },
87 toggleChildItem(childItem, show, options = {}) {
88 const { showPopup, duration } = childItem.data;
89 if (show === undefined)
90 show = !showPopup;
91 if (show === showPopup) {
92 return;
93 }
94 const newChildData = { transition: !options.immediate, showPopup: show };
95 if (!show) {
96 const time = options.immediate ? 0 : duration;
97 this.updateChildData(childItem, Object.assign({}, newChildData), true);
98 setTimeout(() => {
99 this.updateChildData(childItem, { showWrapper: false }, true);
100 }, time);
101 return;
102 }
103 this.getChildWrapperStyle().then((wrapperStyle = '') => {
104 this.updateChildData(childItem, Object.assign(Object.assign({}, newChildData), { wrapperStyle, showWrapper: true }), true);
105 });
106 },
107 close() {
108 this.children.forEach((item) => {
109 this.toggleChildItem(item, false, { immediate: true });
110 });
111 },
112 getChildWrapperStyle() {
113 const { windowHeight } = wx.getSystemInfoSync();
114 const { zIndex, direction } = this.data;
115 let offset = 0;
116 return this.getRect('.van-dropdown-menu').then(rect => {
117 const { top = 0, bottom = 0 } = rect;
118 if (direction === 'down') {
119 offset = bottom;
120 }
121 else {
122 offset = windowHeight - top;
123 }
124 let wrapperStyle = `z-index: ${zIndex};`;
125 if (direction === 'down') {
126 wrapperStyle += `top: ${addUnit(offset)};`;
127 }
128 else {
129 wrapperStyle += `bottom: ${addUnit(offset)};`;
130 }
131 return Promise.resolve(wrapperStyle);
132 });
133 },
134 onTitleTap(event) {
135 // item ---> dropdown-item
136 const { item, index } = event.currentTarget.dataset;
137 if (!item.disabled) {
138 // menuItem ---> dropdown-menu
139 ARRAY.forEach(menuItem => {
140 if (menuItem && menuItem.data.closeOnClickOutside && menuItem !== this) {
141 menuItem.close();
142 }
143 });
144 this.toggleItem(index);
145 }
146 }
147 }
148 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-dropdown-menu van-dropdown-menu--top-bottom">
4 <view
5 wx:for="{{ itemListData }}"
6 wx:key="index"
7 data-item="{{ item }}"
8 data-index="{{ index }}"
9 class="{{ utils.bem('dropdown-menu__item', { disabled: item.disabled }) }}"
10 bind:tap="onTitleTap"
11 >
12 <view
13 class="{{ item.titleClass }} {{ utils.bem('dropdown-menu__title', { active: item.showPopup, down: item.showPopup === (direction === 'down') }) }}"
14 style="{{ item.showPopup ? 'color:' + activeColor : '' }}"
15 >
16 <view class="van-ellipsis">
17 {{item.displayTitle}}
18 </view>
19 </view>
20 </view>
21
22 <slot />
23 </view>
1 @import '../common/index.wxss';.van-dropdown-menu{display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;height:50px;height:var(--dropdown-menu-height,50px);background-color:#fff;background-color:var(--dropdown-menu-background-color,#fff)}.van-dropdown-menu__item{display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:#969799;color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{position:relative;box-sizing:border-box;max-width:100%;padding:0 8px;padding:var(--dropdown-menu-title-padding,0 8px);color:#323233;color:var(--dropdown-menu-title-text-color,#323233);font-size:15px;font-size:var(--dropdown-menu-title-font-size,15px);line-height:18px;line-height:var(--dropdown-menu-title-line-height,18px)}.van-dropdown-menu__title:after{position:absolute;top:50%;right:-4px;margin-top:-5px;border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:.8;content:""}.van-dropdown-menu__title--active{color:#1989fa;color:var(--dropdown-menu-title-active-text-color,#1989fa)}.van-dropdown-menu__title--down:after{margin-top:-1px;-webkit-transform:rotate(135deg);transform:rotate(135deg)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { getSystemInfoSync } from '../common/utils';
2 VantComponent({ 3 VantComponent({
3 field: true, 4 field: true,
4 classes: ['input-class'], 5 classes: ['input-class', 'right-icon-class'],
5 props: { 6 props: {
6 size: String, 7 size: String,
7 icon: String, 8 icon: String,
...@@ -12,27 +13,37 @@ VantComponent({ ...@@ -12,27 +13,37 @@ VantComponent({
12 center: Boolean, 13 center: Boolean,
13 isLink: Boolean, 14 isLink: Boolean,
14 leftIcon: String, 15 leftIcon: String,
16 rightIcon: String,
15 disabled: Boolean, 17 disabled: Boolean,
16 autosize: Boolean, 18 autosize: Boolean,
17 readonly: Boolean, 19 readonly: Boolean,
18 required: Boolean, 20 required: Boolean,
21 password: Boolean,
19 iconClass: String, 22 iconClass: String,
20 clearable: Boolean, 23 clearable: Boolean,
24 clickable: Boolean,
21 inputAlign: String, 25 inputAlign: String,
22 errorMessageAlign: String, 26 placeholder: String,
23 customClass: String, 27 customStyle: String,
24 confirmType: String, 28 confirmType: String,
25 confirmHold: Boolean, 29 confirmHold: Boolean,
30 holdKeyboard: Boolean,
26 errorMessage: String, 31 errorMessage: String,
27 placeholder: String, 32 arrowDirection: String,
28 customStyle: String, 33 placeholderStyle: String,
29 useIconSlot: Boolean, 34 errorMessageAlign: String,
30 useButtonSlot: Boolean, 35 selectionEnd: {
36 type: Number,
37 value: -1
38 },
39 selectionStart: {
40 type: Number,
41 value: -1
42 },
31 showConfirmBar: { 43 showConfirmBar: {
32 type: Boolean, 44 type: Boolean,
33 value: true 45 value: true
34 }, 46 },
35 placeholderStyle: String,
36 adjustPosition: { 47 adjustPosition: {
37 type: Boolean, 48 type: Boolean,
38 value: true 49 value: true
...@@ -59,63 +70,29 @@ VantComponent({ ...@@ -59,63 +70,29 @@ VantComponent({
59 } 70 }
60 }, 71 },
61 data: { 72 data: {
62 showClear: false 73 focused: false,
63 }, 74 system: getSystemInfoSync().system.split(' ').shift().toLowerCase()
64 beforeCreate() {
65 this.focused = false;
66 }, 75 },
67 methods: { 76 methods: {
68 onInput(event) { 77 onInput(event) {
69 const { value = '' } = event.detail || {}; 78 const { value = '' } = event.detail || {};
70 this.set({ 79 this.setData({ value }, () => {
71 value,
72 showClear: this.getShowClear(value)
73 }, () => {
74 this.emitChange(value); 80 this.emitChange(value);
75 }); 81 });
76 }, 82 },
77 onFocus(event) { 83 onFocus(event) {
78 const { value = '', height = 0 } = event.detail || {}; 84 this.setData({ focused: true });
79 this.$emit('focus', { value, height }); 85 this.$emit('focus', event.detail);
80 this.focused = true;
81 this.blurFromClear = false;
82 this.set({
83 showClear: this.getShowClear()
84 });
85 }, 86 },
86 onBlur(event) { 87 onBlur(event) {
87 const { value = '', cursor = 0 } = event.detail || {}; 88 this.setData({ focused: false });
88 this.$emit('blur', { value, cursor }); 89 this.$emit('blur', event.detail);
89 this.focused = false;
90 const showClear = this.getShowClear();
91 if (this.data.value === value) {
92 this.set({
93 showClear
94 });
95 }
96 else if (!this.blurFromClear) {
97 // fix: the handwritten keyboard does not trigger input change
98 this.set({
99 value,
100 showClear
101 }, () => {
102 this.emitChange(value);
103 });
104 }
105 }, 90 },
106 onClickIcon() { 91 onClickIcon() {
107 this.$emit('click-icon'); 92 this.$emit('click-icon');
108 }, 93 },
109 getShowClear(value) {
110 value = value === undefined ? this.data.value : value;
111 return (this.data.clearable && this.focused && value && !this.data.readonly);
112 },
113 onClear() { 94 onClear() {
114 this.blurFromClear = true; 95 this.setData({ value: '' }, () => {
115 this.set({
116 value: '',
117 showClear: this.getShowClear('')
118 }, () => {
119 this.emitChange(''); 96 this.emitChange('');
120 this.$emit('clear', ''); 97 this.$emit('clear', '');
121 }); 98 });
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <van-cell 3 <van-cell
4 size="{{ size }}"
4 icon="{{ leftIcon }}" 5 icon="{{ leftIcon }}"
5 title="{{ label }}" 6 title="{{ label }}"
6 center="{{ center }}" 7 center="{{ center }}"
7 border="{{ border }}" 8 border="{{ border }}"
8 is-link="{{ isLink }}" 9 is-link="{{ isLink }}"
9 required="{{ required }}" 10 required="{{ required }}"
10 custom-style="{{ customStyle }}" 11 clickable="{{ clickable }}"
11 title-width="{{ titleWidth }}" 12 title-width="{{ titleWidth }}"
13 custom-style="{{ customStyle }}"
14 arrow-direction="{{ arrowDirection }}"
12 custom-class="van-field" 15 custom-class="van-field"
13 size="{{ size }}"
14 > 16 >
15 <slot name="left-icon" slot="icon" /> 17 <slot name="left-icon" slot="icon" />
16 <slot name="label" slot="title" /> 18 <slot name="label" slot="title" />
17 <view class="van-field__body {{ type === 'textarea' ? 'van-field__body--textarea' : '' }}"> 19 <view class="{{ utils.bem('field__body', [type, system]) }}">
18 <textarea 20 <textarea
19 wx:if="{{ type === 'textarea' }}" 21 wx:if="{{ type === 'textarea' }}"
20 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}" 22 class="input-class {{ utils.bem('field__input', [inputAlign, type, { disabled, error }]) }}"
21 fixed="{{ fixed }}" 23 fixed="{{ fixed }}"
22 focus="{{ focus }}" 24 focus="{{ focus }}"
23 value="{{ value }}" 25 value="{{ value }}"
24 disabled="{{ disabled || readonly }}" 26 disabled="{{ disabled || readonly }}"
25 maxlength="{{ maxlength }}" 27 maxlength="{{ maxlength }}"
26 auto-height="{{ autosize }}"
27 placeholder="{{ placeholder }}" 28 placeholder="{{ placeholder }}"
28 placeholder-style="{{ placeholderStyle }}" 29 placeholder-style="{{ placeholderStyle }}"
29 placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}" 30 placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
31 auto-height="{{ autosize }}"
30 cursor-spacing="{{ cursorSpacing }}" 32 cursor-spacing="{{ cursorSpacing }}"
31 adjust-position="{{ adjustPosition }}" 33 adjust-position="{{ adjustPosition }}"
32 show-confirm-bar="{{ showConfirmBar }}" 34 show-confirm-bar="{{ showConfirmBar }}"
35 hold-keyboard="{{ holdKeyboard }}"
36 selection-end="{{ selectionEnd }}"
37 selection-start="{{ selectionStart }}"
33 bindinput="onInput" 38 bindinput="onInput"
34 bind:blur="onBlur" 39 bind:blur="onBlur"
35 bind:focus="onFocus" 40 bind:focus="onFocus"
36 bind:confirm="onConfirm" 41 bind:confirm="onConfirm"
37 /> 42 >
43 </textarea>
38 <input 44 <input
39 wx:else 45 wx:else
40 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}" 46 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
...@@ -45,34 +51,39 @@ ...@@ -45,34 +51,39 @@
45 maxlength="{{ maxlength }}" 51 maxlength="{{ maxlength }}"
46 placeholder="{{ placeholder }}" 52 placeholder="{{ placeholder }}"
47 placeholder-style="{{ placeholderStyle }}" 53 placeholder-style="{{ placeholderStyle }}"
48 placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}" 54 placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
49 confirm-type="{{ confirmType }}" 55 confirm-type="{{ confirmType }}"
50 confirm-hold="{{ confirmHold }}" 56 confirm-hold="{{ confirmHold }}"
57 hold-keyboard="{{ holdKeyboard }}"
51 cursor-spacing="{{ cursorSpacing }}" 58 cursor-spacing="{{ cursorSpacing }}"
52 adjust-position="{{ adjustPosition }}" 59 adjust-position="{{ adjustPosition }}"
60 selection-end="{{ selectionEnd }}"
61 selection-start="{{ selectionStart }}"
62 password="{{ password || type === 'password' }}"
53 bindinput="onInput" 63 bindinput="onInput"
54 bind:blur="onBlur" 64 bind:blur="onBlur"
55 bind:focus="onFocus" 65 bind:focus="onFocus"
56 bind:confirm="onConfirm" 66 bind:confirm="onConfirm"
57 /> 67 />
58 <van-icon 68 <van-icon
59 wx:if="{{ showClear }}" 69 wx:if="{{ clearable && focused && value && !readonly }}"
60 size="16px" 70 size="16px"
61 name="clear" 71 name="clear"
62 class="van-field__clear-root" 72 class="van-field__clear-root van-field__icon-root"
63 custom-class="van-field__clear" 73 bindtouchstart="onClear"
64 bind:touchstart="onClear"
65 /> 74 />
66 <view class="van-field__icon-container" wx:if="{{ icon || useIconSlot }}" bind:tap="onClickIcon"> 75 <view class="van-field__icon-container" bind:tap="onClickIcon">
67 <van-icon 76 <van-icon
68 wx:if="{{ icon }}" 77 wx:if="{{ rightIcon || icon }}"
69 size="16px" 78 size="16px"
70 name="{{ icon }}" 79 name="{{ rightIcon || icon }}"
71 custom-class="van-field__icon {{ iconClass }}" 80 class="van-field__icon-root {{ iconClass }}"
81 custom-class="right-icon-class"
72 /> 82 />
73 <slot wx:else name="icon" /> 83 <slot name="right-icon" />
84 <slot name="icon" />
74 </view> 85 </view>
75 <view wx:if="{{ useButtonSlot }}" class="van-field__button"> 86 <view class="van-field__button">
76 <slot name="button" /> 87 <slot name="button" />
77 </view> 88 </view>
78 </view> 89 </view>
......
1 @import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{min-height:24px}.van-field__input{display:block;width:100%;height:24px;min-height:24px;padding:0;margin:0;line-height:inherit;color:#333;text-align:left;background-color:initial;border:0;box-sizing:border-box;resize:none}.van-field__input--disabled{color:#999;background-color:initial;opacity:1}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__input--error{color:#f44}.van-field__placeholder{color:#999}.van-field__clear-root{display:-webkit-flex;display:flex;height:24px;-webkit-align-items:center;align-items:center}.van-field__button,.van-field__clear,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear,.van-field__icon-container{padding:0 10px;margin-right:-10px;line-height:inherit;vertical-align:middle}.van-field__clear{color:#c9c9c9}.van-field__icon-container{color:#999}.van-field__icon{display:block!important}.van-field__button{padding-left:10px}.van-field__error-message{font-size:12px;color:#f44;text-align:left}.van-field__error--center{text-align:center}.van-field__error--right{text-align:right}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{line-height:1.2em;min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__body--textarea.van-field__body--ios{margin-top:-4.5px}.van-field__input{position:relative;display:block;box-sizing:border-box;width:100%;margin:0;padding:0;line-height:inherit;text-align:left;background-color:initial;border:0;resize:none;color:#323233;color:var(--field-input-text-color,#323233);height:24px;height:var(--cell-line-height,24px);min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__input--textarea{height:18px;height:var(--field-text-area-min-height,18px);min-height:18px;min-height:var(--field-text-area-min-height,18px)}.van-field__input--error{color:#ee0a24;color:var(--field-input-error-text-color,#ee0a24)}.van-field__input--disabled{background-color:initial;opacity:1;color:#969799;color:var(--field-input-disabled-text-color,#969799)}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__placeholder{position:absolute;top:0;right:0;left:0;pointer-events:none;color:#969799;color:var(--field-placeholder-text-color,#969799)}.van-field__placeholder--error{color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;vertical-align:middle;padding:0 8px;padding:0 var(--padding-xs,8px);margin-right:-8px;margin-right:-var(--padding-xs,8px)}.van-field__button,.van-field__clear-root,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear-root{color:#c8c9cc;color:var(--field-clear-icon-color,#c8c9cc)}.van-field__icon-container{color:#969799;color:var(--field-icon-container-color,#969799)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:8px;padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{text-align:left;font-size:12px;font-size:var(--field-error-message-text-font-size,12px);color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -4,8 +4,16 @@ import { button } from '../mixins/button'; ...@@ -4,8 +4,16 @@ import { button } from '../mixins/button';
4 import { openType } from '../mixins/open-type'; 4 import { openType } from '../mixins/open-type';
5 VantComponent({ 5 VantComponent({
6 mixins: [link, button, openType], 6 mixins: [link, button, openType],
7 relation: {
8 type: 'ancestor',
9 name: 'goods-action',
10 linked(parent) {
11 this.parent = parent;
12 }
13 },
7 props: { 14 props: {
8 text: String, 15 text: String,
16 color: String,
9 loading: Boolean, 17 loading: Boolean,
10 disabled: Boolean, 18 disabled: Boolean,
11 type: { 19 type: {
...@@ -13,10 +21,21 @@ VantComponent({ ...@@ -13,10 +21,21 @@ VantComponent({
13 value: 'danger' 21 value: 'danger'
14 } 22 }
15 }, 23 },
24 mounted() {
25 this.updateStyle();
26 },
16 methods: { 27 methods: {
17 onClick(event) { 28 onClick(event) {
18 this.$emit('click', event.detail); 29 this.$emit('click', event.detail);
19 this.jumpLink(); 30 this.jumpLink();
31 },
32 updateStyle() {
33 const { children = [] } = this.parent;
34 const index = children.indexOf(this);
35 this.setData({
36 isFirst: index === 0,
37 isLast: index === children.length - 1
38 });
20 } 39 }
21 } 40 }
22 }); 41 });
......
1 <wxs src="../wxs/utils.wxs" module="utils" />
1 <van-button 2 <van-button
2 square 3 square
3 id="{{ id }}" 4 id="{{ id }}"
4 size="large"
5 lang="{{ lang }}" 5 lang="{{ lang }}"
6 type="{{ type }}" 6 type="{{ type }}"
7 color="{{ color }}"
7 loading="{{ loading }}" 8 loading="{{ loading }}"
8 disabled="{{ disabled }}" 9 disabled="{{ disabled }}"
9 open-type="{{ openType }}" 10 open-type="{{ openType }}"
10 custom-class="custom-class" 11 custom-class="{{ utils.bem('goods-action-button', [type, { first: isFirst, last: isLast }]) }}"
11 business-id="{{ businessId }}" 12 business-id="{{ businessId }}"
12 session-from="{{ sessionFrom }}" 13 session-from="{{ sessionFrom }}"
13 app-parameter="{{ appParameter }}" 14 app-parameter="{{ appParameter }}"
......
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-goods-action-button{border:none!important;height:40px!important;height:var(--goods-action-button-height,40px)!important;font-weight:500!important;font-weight:var(--font-weight-bold,500)!important;line-height:40px!important;line-height:var(--goods-action-button-height,40px)!important}.van-goods-action-button--first{display:block!important;margin-left:5px;border-top-left-radius:20px!important;border-top-left-radius:var(--goods-action-button-border-radius,20px)!important;border-bottom-left-radius:20px!important;border-bottom-left-radius:var(--goods-action-button-border-radius,20px)!important}.van-goods-action-button--last{display:block!important;margin-right:5px;border-top-right-radius:20px!important;border-top-right-radius:var(--goods-action-button-border-radius,20px)!important;border-bottom-right-radius:20px!important;border-bottom-right-radius:var(--goods-action-button-border-radius,20px)!important}.van-goods-action-button--warning{background:linear-gradient(90deg,#ffd01e,#ff8917);background:var(--goods-action-button-warning-color,linear-gradient(90deg,#ffd01e,#ff8917))}.van-goods-action-button--danger{background:linear-gradient(90deg,#ff6034,#ee0a24);background:var(--goods-action-button-danger-color,linear-gradient(90deg,#ff6034,#ee0a24))}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -7,6 +7,7 @@ VantComponent({ ...@@ -7,6 +7,7 @@ VantComponent({
7 mixins: [link, button, openType], 7 mixins: [link, button, openType],
8 props: { 8 props: {
9 text: String, 9 text: String,
10 dot: Boolean,
10 info: String, 11 info: String,
11 icon: String, 12 icon: String,
12 disabled: Boolean, 13 disabled: Boolean,
......
...@@ -22,14 +22,17 @@ ...@@ -22,14 +22,17 @@
22 bindgetphonenumber="bindGetPhoneNumber" 22 bindgetphonenumber="bindGetPhoneNumber"
23 bindlaunchapp="bindLaunchApp" 23 bindlaunchapp="bindLaunchApp"
24 > 24 >
25 <view class="van-goods-action-icon__content van-hairline--right"> 25 <view class="van-goods-action-icon__content">
26 <van-icon 26 <van-icon
27 wx:if="{{ icon }}"
27 size="20px" 28 size="20px"
28 name="{{ icon }}" 29 name="{{ icon }}"
30 dot="{{ dot }}"
29 info="{{ info }}" 31 info="{{ info }}"
30 class="van-goods-action-icon__icon" 32 class="van-goods-action-icon__icon"
31 custom-class="icon-class" 33 custom-class="icon-class"
32 /> 34 />
35 <slot name="icon" />
33 <text class="text-class">{{ text }}</text> 36 <text class="text-class">{{ text }}</text>
34 </view> 37 </view>
35 </van-button> 38 </van-button>
......
1 @import '../common/index.wxss';.van-goods-action-icon{width:50px!important;border:none!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;height:100%;font-size:10px;line-height:1;color:#7d7e80;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-goods-action-icon__icon{margin-bottom:4px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-goods-action-icon{border:none!important;width:50px!important;width:var(--goods-action-icon-height,50px)!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;height:100%;line-height:1;font-size:10px;font-size:var(--goods-action-icon-font-size,10px);color:#7d7e80;color:var(--goods-action-icon-text-color,#7d7e80)}.van-goods-action-icon__icon{margin-bottom:4px}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({ 2 VantComponent({
4 mixins: [safeArea()] 3 relation: {
4 type: 'descendant',
5 name: 'goods-action-button',
6 linked(child) {
7 this.children.push(child);
8 },
9 unlinked(child) {
10 this.children = this.children.filter((item) => item !== child);
11 }
12 },
13 beforeCreate() {
14 this.children = [];
15 },
16 props: {
17 safeAreaInsetBottom: {
18 type: Boolean,
19 value: true
20 }
21 }
5 }); 22 });
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <view class="custom-class {{ utils.bem('goods-action', { safe: isIPhoneX && safeAreaInsetBottom }) }}"> 3 <view class="custom-class {{ utils.bem('goods-action', { safe: safeAreaInsetBottom }) }}">
4 <slot /> 4 <slot />
5 </view> 5 </view>
......
1 @import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-goods-action--safe{padding-bottom:34px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;background-color:#fff;background-color:var(--goods-action-background-color,#fff)}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { link } from '../mixins/link';
2 import { VantComponent } from '../common/component';
3 VantComponent({
4 relation: {
5 name: 'grid',
6 type: 'ancestor',
7 linked(parent) {
8 this.parent = parent;
9 }
10 },
11 mixins: [link],
12 props: {
13 icon: String,
14 dot: Boolean,
15 info: null,
16 text: String,
17 useSlot: Boolean
18 },
19 mounted() {
20 this.updateStyle();
21 },
22 methods: {
23 updateStyle() {
24 if (!this.parent) {
25 return;
26 }
27 const { data, children } = this.parent;
28 const { columnNum, border, square, gutter, clickable, center } = data;
29 const width = `${100 / columnNum}%`;
30 const styleWrapper = [];
31 styleWrapper.push(`width: ${width}`);
32 if (square) {
33 styleWrapper.push(`padding-top: ${width}`);
34 }
35 if (gutter) {
36 styleWrapper.push(`padding-right: ${gutter}px`);
37 const index = children.indexOf(this);
38 if (index >= columnNum) {
39 styleWrapper.push(`margin-top: ${gutter}px`);
40 }
41 }
42 this.setData({
43 style: styleWrapper.join('; '),
44 center,
45 border,
46 square,
47 gutter,
48 clickable
49 });
50 },
51 onClick() {
52 this.$emit('click');
53 this.jumpLink();
54 }
55 }
56 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="{{ utils.bem('grid-item', { square }) }}" style="{{ style }}" bindtap="onClick">
4 <view class="{{ utils.bem('grid-item__content', { center, square, clickable, surround: border && gutter }) }} {{ border ? 'van-hairline--surround' : '' }}">
5 <block wx:if="{{ useSlot }}">
6 <slot />
7 </block>
8 <block wx:else>
9 <view class="van-grid-item__icon">
10 <van-icon wx:if="{{ icon }}" name="{{ icon }}" dot="{{ dot }}" info="{{ info }}" />
11 <slot wx:else name="icon"></slot>
12 </view>
13 <view class="van-grid-item__text">
14 <text wx:if="{{ text }}">{{ text }}</text>
15 <slot wx:else name="text"></slot>
16 </view>
17 </block>
18 </view>
19 </view>
1 @import '../common/index.wxss';.van-grid-item{position:relative;float:left;box-sizing:border-box}.van-grid-item--square{height:0}.van-grid-item__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;box-sizing:border-box;height:100%;padding:16px 8px;padding:var(--grid-item-content-padding,16px 8px);background-color:#fff;background-color:var(--grid-item-content-background-color,#fff)}.van-grid-item__content:after{z-index:1;border-width:0 1px 1px 0;border-bottom-width:var(--border-width-base,1px);border-right-width:var(--border-width-base,1px);border-top-width:0}.van-grid-item__content--surround:after{border-width:1px;border-width:var(--border-width-base,1px)}.van-grid-item__content--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-grid-item__content--square{position:absolute;top:0;right:0;left:0}.van-grid-item__content--clickable:active{background-color:#f2f3f5;background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{font-size:26px;font-size:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:#7d7e80;color:var(--grid-item-text-color,#7d7e80);font-size:12px;font-size:var(--grid-item-text-font-size,12px)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'grid-item',
5 type: 'descendant',
6 linked(child) {
7 this.children.push(child);
8 },
9 unlinked(child) {
10 this.children = this.children.filter((item) => item !== child);
11 }
12 },
13 props: {
14 square: {
15 type: Boolean,
16 observer: 'updateChildren'
17 },
18 gutter: {
19 type: [Number, String],
20 value: 0,
21 observer: 'updateChildren'
22 },
23 clickable: {
24 type: Boolean,
25 observer: 'updateChildren'
26 },
27 columnNum: {
28 type: Number,
29 value: 4,
30 observer: 'updateChildren'
31 },
32 center: {
33 type: Boolean,
34 value: true,
35 observer: 'updateChildren'
36 },
37 border: {
38 type: Boolean,
39 value: true,
40 observer: 'updateChildren'
41 }
42 },
43 beforeCreate() {
44 this.children = [];
45 },
46 created() {
47 const { gutter } = this.data;
48 if (gutter) {
49 this.setData({
50 style: `padding-left: ${gutter}px`
51 });
52 }
53 },
54 methods: {
55 updateChildren() {
56 this.children.forEach((child) => {
57 child.updateStyle();
58 });
59 }
60 }
61 });
1 {
2 "component": true
3 }
1 <view class="van-grid {{ border && !gutter ? 'van-hairline--top' : '' }}" style="{{ style }}">
2 <slot />
3 </view>
1 @import '../common/index.wxss';.van-grid{position:relative;box-sizing:border-box;overflow:hidden}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { addUnit } from '../common/utils';
2 VantComponent({ 3 VantComponent({
3 props: { 4 props: {
5 dot: Boolean,
4 info: null, 6 info: null,
5 name: String, 7 size: {
6 size: String, 8 type: null,
9 observer: 'setSizeWithUnit'
10 },
7 color: String, 11 color: String,
8 customStyle: String, 12 customStyle: String,
9 classPrefix: { 13 classPrefix: {
10 type: String, 14 type: String,
11 value: 'van-icon' 15 value: 'van-icon'
16 },
17 name: {
18 type: String,
19 observer(val) {
20 this.setData({
21 isImageName: val.indexOf('/') !== -1
22 });
23 }
12 } 24 }
13 }, 25 },
26 data: {
27 sizeWithUnit: null,
28 },
14 methods: { 29 methods: {
15 onClick() { 30 onClick() {
16 this.$emit('click'); 31 this.$emit('click');
32 },
33 setSizeWithUnit(size) {
34 this.setData({
35 sizeWithUnit: addUnit(size)
36 });
17 } 37 }
18 } 38 }
19 }); 39 });
......
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view 1 <view
4 class="custom-class {{ classPrefix }} {{ utils.isSrc(name) ? 'van-icon--image' : classPrefix + '-' + name }}" 2 class="custom-class {{ classPrefix }} {{ isImageName ? 'van-icon--image' : classPrefix + '-' + name }}"
5 style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + ';' : '' }}{{ customStyle }}" 3 style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + sizeWithUnit + ';' : '' }}{{ customStyle }}"
6 bind:tap="onClick" 4 bind:tap="onClick"
7 > 5 >
8 <van-info 6 <van-info
9 wx:if="{{ info !== null }}" 7 wx:if="{{ info !== null || dot }}"
8 dot="{{ dot }}"
10 info="{{ info }}" 9 info="{{ info }}"
11 custom-class="van-icon__info" 10 custom-class="van-icon__info"
12 /> 11 />
13 <image 12 <image
14 wx:if="{{ utils.isSrc(name) }}" 13 wx:if="{{ isImageName }}"
15 src="{{ name }}" 14 src="{{ name }}"
15 mode="aspectFit"
16 class="van-icon__image" 16 class="van-icon__image"
17 /> 17 />
18 </view> 18 </view>
......
1 @import '../common/index.wxss';@font-face{font-style:normal;font-weight:400;font-family:vant-icon;src:url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-o:before{content:"\F03A"}.van-icon-comment:before{content:"\F03B"}.van-icon-completed:before{content:"\F03C"}.van-icon-contact:before{content:"\F03D"}.van-icon-coupon-o:before{content:"\F03E"}.van-icon-coupon:before{content:"\F03F"}.van-icon-credit-pay:before{content:"\F040"}.van-icon-cross:before{content:"\F041"}.van-icon-debit-pay:before{content:"\F042"}.van-icon-delete:before{content:"\F043"}.van-icon-descending:before{content:"\F044"}.van-icon-description:before{content:"\F045"}.van-icon-desktop-o:before{content:"\F046"}.van-icon-diamond-o:before{content:"\F047"}.van-icon-diamond:before{content:"\F048"}.van-icon-discount:before{content:"\F049"}.van-icon-ecard-pay:before{content:"\F04A"}.van-icon-edit:before{content:"\F04B"}.van-icon-ellipsis:before{content:"\F04C"}.van-icon-empty:before{content:"\F04D"}.van-icon-envelop-o:before{content:"\F04E"}.van-icon-exchange:before{content:"\F04F"}.van-icon-expand-o:before{content:"\F050"}.van-icon-expand:before{content:"\F051"}.van-icon-eye-o:before{content:"\F052"}.van-icon-eye:before{content:"\F053"}.van-icon-fail:before{content:"\F054"}.van-icon-failure:before{content:"\F055"}.van-icon-filter-o:before{content:"\F056"}.van-icon-fire-o:before{content:"\F057"}.van-icon-fire:before{content:"\F058"}.van-icon-flag-o:before{content:"\F059"}.van-icon-flower-o:before{content:"\F05A"}.van-icon-free-postage:before{content:"\F05B"}.van-icon-friends-o:before{content:"\F05C"}.van-icon-friends:before{content:"\F05D"}.van-icon-gem-o:before{content:"\F05E"}.van-icon-gem:before{content:"\F05F"}.van-icon-gift-card-o:before{content:"\F060"}.van-icon-gift-card:before{content:"\F061"}.van-icon-gift-o:before{content:"\F062"}.van-icon-gift:before{content:"\F063"}.van-icon-gold-coin-o:before{content:"\F064"}.van-icon-gold-coin:before{content:"\F065"}.van-icon-goods-collect-o:before{content:"\F066"}.van-icon-goods-collect:before{content:"\F067"}.van-icon-graphic:before{content:"\F068"}.van-icon-home-o:before{content:"\F069"}.van-icon-hot-o:before{content:"\F06A"}.van-icon-hot-sale-o:before{content:"\F06B"}.van-icon-hot-sale:before{content:"\F06C"}.van-icon-hot:before{content:"\F06D"}.van-icon-hotel-o:before{content:"\F06E"}.van-icon-idcard:before{content:"\F06F"}.van-icon-info-o:before{content:"\F070"}.van-icon-info:before{content:"\F071"}.van-icon-invition:before{content:"\F072"}.van-icon-label-o:before{content:"\F073"}.van-icon-label:before{content:"\F074"}.van-icon-like-o:before{content:"\F075"}.van-icon-like:before{content:"\F076"}.van-icon-live:before{content:"\F077"}.van-icon-location-o:before{content:"\F078"}.van-icon-location:before{content:"\F079"}.van-icon-lock:before{content:"\F07A"}.van-icon-logistics:before{content:"\F07B"}.van-icon-manager-o:before{content:"\F07C"}.van-icon-manager:before{content:"\F07D"}.van-icon-map-marked:before{content:"\F07E"}.van-icon-medel-o:before{content:"\F07F"}.van-icon-medel:before{content:"\F080"}.van-icon-more-o:before{content:"\F081"}.van-icon-more:before{content:"\F082"}.van-icon-music-o:before{content:"\F083"}.van-icon-new-arrival-o:before{content:"\F084"}.van-icon-new-arrival:before{content:"\F085"}.van-icon-new-o:before{content:"\F086"}.van-icon-new:before{content:"\F087"}.van-icon-newspaper-o:before{content:"\F088"}.van-icon-notes-o:before{content:"\F089"}.van-icon-orders-o:before{content:"\F08A"}.van-icon-other-pay:before{content:"\F08B"}.van-icon-paid:before{content:"\F08C"}.van-icon-passed:before{content:"\F08D"}.van-icon-pause-circle-o:before{content:"\F08E"}.van-icon-pause-circle:before{content:"\F08F"}.van-icon-pause:before{content:"\F090"}.van-icon-peer-pay:before{content:"\F091"}.van-icon-pending-payment:before{content:"\F092"}.van-icon-phone-circle-o:before{content:"\F093"}.van-icon-phone-o:before{content:"\F094"}.van-icon-phone:before{content:"\F095"}.van-icon-photo-o:before{content:"\F096"}.van-icon-photo:before{content:"\F097"}.van-icon-photograph:before{content:"\F098"}.van-icon-play-circle-o:before{content:"\F099"}.van-icon-play-circle:before{content:"\F09A"}.van-icon-play:before{content:"\F09B"}.van-icon-plus:before{content:"\F09C"}.van-icon-point-gift-o:before{content:"\F09D"}.van-icon-point-gift:before{content:"\F09E"}.van-icon-points:before{content:"\F09F"}.van-icon-printer:before{content:"\F0A0"}.van-icon-qr-invalid:before{content:"\F0A1"}.van-icon-qr:before{content:"\F0A2"}.van-icon-question-o:before{content:"\F0A3"}.van-icon-question:before{content:"\F0A4"}.van-icon-records:before{content:"\F0A5"}.van-icon-refund-o:before{content:"\F0A6"}.van-icon-replay:before{content:"\F0A7"}.van-icon-scan:before{content:"\F0A8"}.van-icon-search:before{content:"\F0A9"}.van-icon-send-gift-o:before{content:"\F0AA"}.van-icon-send-gift:before{content:"\F0AB"}.van-icon-service-o:before{content:"\F0AC"}.van-icon-service:before{content:"\F0AD"}.van-icon-setting-o:before{content:"\F0AE"}.van-icon-setting:before{content:"\F0AF"}.van-icon-share:before{content:"\F0B0"}.van-icon-shop-collect-o:before{content:"\F0B1"}.van-icon-shop-collect:before{content:"\F0B2"}.van-icon-shop-o:before{content:"\F0B3"}.van-icon-shop:before{content:"\F0B4"}.van-icon-shopping-cart-o:before{content:"\F0B5"}.van-icon-shopping-cart:before{content:"\F0B6"}.van-icon-shrink:before{content:"\F0B7"}.van-icon-sign:before{content:"\F0B8"}.van-icon-smile-comment-o:before{content:"\F0B9"}.van-icon-smile-comment:before{content:"\F0BA"}.van-icon-smile-o:before{content:"\F0BB"}.van-icon-star-o:before{content:"\F0BC"}.van-icon-star:before{content:"\F0BD"}.van-icon-stop-circle-o:before{content:"\F0BE"}.van-icon-stop-circle:before{content:"\F0BF"}.van-icon-stop:before{content:"\F0C0"}.van-icon-success:before{content:"\F0C1"}.van-icon-thumb-circle-o:before{content:"\F0C2"}.van-icon-todo-list-o:before{content:"\F0C3"}.van-icon-todo-list:before{content:"\F0C4"}.van-icon-tosend:before{content:"\F0C5"}.van-icon-tv-o:before{content:"\F0C6"}.van-icon-umbrella-circle:before{content:"\F0C7"}.van-icon-underway-o:before{content:"\F0C8"}.van-icon-underway:before{content:"\F0C9"}.van-icon-upgrade:before{content:"\F0CA"}.van-icon-user-circle-o:before{content:"\F0CB"}.van-icon-user-o:before{content:"\F0CC"}.van-icon-video-o:before{content:"\F0CD"}.van-icon-video:before{content:"\F0CE"}.van-icon-vip-card-o:before{content:"\F0CF"}.van-icon-vip-card:before{content:"\F0D0"}.van-icon-volume-o:before{content:"\F0D1"}.van-icon-volume:before{content:"\F0D2"}.van-icon-wap-home:before{content:"\F0D3"}.van-icon-wap-nav:before{content:"\F0D4"}.van-icon-warn-o:before{content:"\F0D5"}.van-icon-warning-o:before{content:"\F0D6"}.van-icon-weapp-nav:before{content:"\F0D7"}.van-icon-wechat:before{content:"\F0D8"}.van-icon-youzan-shield:before{content:"\F0D9"}.van-icon--image{width:1em;height:1em}.van-icon__image{position:absolute;top:0;right:0;bottom:0;left:0;max-width:100%;max-height:100%;margin:auto}.van-icon__info{z-index:1}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';@font-face{font-weight:400;font-family:vant-icon;font-style:normal;font-display:auto;src:url(https://img.yzcdn.cn/vant/vant-icon-0bc654.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-0bc654.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-0bc654.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-circle:before{content:"\F03A"}.van-icon-comment-o:before{content:"\F03B"}.van-icon-comment:before{content:"\F03C"}.van-icon-completed:before{content:"\F03D"}.van-icon-contact:before{content:"\F03E"}.van-icon-coupon-o:before{content:"\F03F"}.van-icon-coupon:before{content:"\F040"}.van-icon-credit-pay:before{content:"\F041"}.van-icon-cross:before{content:"\F042"}.van-icon-debit-pay:before{content:"\F043"}.van-icon-delete:before{content:"\F044"}.van-icon-descending:before{content:"\F045"}.van-icon-description:before{content:"\F046"}.van-icon-desktop-o:before{content:"\F047"}.van-icon-diamond-o:before{content:"\F048"}.van-icon-diamond:before{content:"\F049"}.van-icon-discount:before{content:"\F04A"}.van-icon-down:before{content:"\F04B"}.van-icon-ecard-pay:before{content:"\F04C"}.van-icon-edit:before{content:"\F04D"}.van-icon-ellipsis:before{content:"\F04E"}.van-icon-empty:before{content:"\F04F"}.van-icon-envelop-o:before{content:"\F050"}.van-icon-exchange:before{content:"\F051"}.van-icon-expand-o:before{content:"\F052"}.van-icon-expand:before{content:"\F053"}.van-icon-eye-o:before{content:"\F054"}.van-icon-eye:before{content:"\F055"}.van-icon-fail:before{content:"\F056"}.van-icon-failure:before{content:"\F057"}.van-icon-filter-o:before{content:"\F058"}.van-icon-fire-o:before{content:"\F059"}.van-icon-fire:before{content:"\F05A"}.van-icon-flag-o:before{content:"\F05B"}.van-icon-flower-o:before{content:"\F05C"}.van-icon-free-postage:before{content:"\F05D"}.van-icon-friends-o:before{content:"\F05E"}.van-icon-friends:before{content:"\F05F"}.van-icon-gem-o:before{content:"\F060"}.van-icon-gem:before{content:"\F061"}.van-icon-gift-card-o:before{content:"\F062"}.van-icon-gift-card:before{content:"\F063"}.van-icon-gift-o:before{content:"\F064"}.van-icon-gift:before{content:"\F065"}.van-icon-gold-coin-o:before{content:"\F066"}.van-icon-gold-coin:before{content:"\F067"}.van-icon-good-job-o:before{content:"\F068"}.van-icon-good-job:before{content:"\F069"}.van-icon-goods-collect-o:before{content:"\F06A"}.van-icon-goods-collect:before{content:"\F06B"}.van-icon-graphic:before{content:"\F06C"}.van-icon-home-o:before{content:"\F06D"}.van-icon-hot-o:before{content:"\F06E"}.van-icon-hot-sale-o:before{content:"\F06F"}.van-icon-hot-sale:before{content:"\F070"}.van-icon-hot:before{content:"\F071"}.van-icon-hotel-o:before{content:"\F072"}.van-icon-idcard:before{content:"\F073"}.van-icon-info-o:before{content:"\F074"}.van-icon-info:before{content:"\F075"}.van-icon-invition:before{content:"\F076"}.van-icon-label-o:before{content:"\F077"}.van-icon-label:before{content:"\F078"}.van-icon-like-o:before{content:"\F079"}.van-icon-like:before{content:"\F07A"}.van-icon-live:before{content:"\F07B"}.van-icon-location-o:before{content:"\F07C"}.van-icon-location:before{content:"\F07D"}.van-icon-lock:before{content:"\F07E"}.van-icon-logistics:before{content:"\F07F"}.van-icon-manager-o:before{content:"\F080"}.van-icon-manager:before{content:"\F081"}.van-icon-map-marked:before{content:"\F082"}.van-icon-medel-o:before{content:"\F083"}.van-icon-medel:before{content:"\F084"}.van-icon-more-o:before{content:"\F085"}.van-icon-more:before{content:"\F086"}.van-icon-music-o:before{content:"\F087"}.van-icon-music:before{content:"\F088"}.van-icon-new-arrival-o:before{content:"\F089"}.van-icon-new-arrival:before{content:"\F08A"}.van-icon-new-o:before{content:"\F08B"}.van-icon-new:before{content:"\F08C"}.van-icon-newspaper-o:before{content:"\F08D"}.van-icon-notes-o:before{content:"\F08E"}.van-icon-orders-o:before{content:"\F08F"}.van-icon-other-pay:before{content:"\F090"}.van-icon-paid:before{content:"\F091"}.van-icon-passed:before{content:"\F092"}.van-icon-pause-circle-o:before{content:"\F093"}.van-icon-pause-circle:before{content:"\F094"}.van-icon-pause:before{content:"\F095"}.van-icon-peer-pay:before{content:"\F096"}.van-icon-pending-payment:before{content:"\F097"}.van-icon-phone-circle-o:before{content:"\F098"}.van-icon-phone-circle:before{content:"\F099"}.van-icon-phone-o:before{content:"\F09A"}.van-icon-phone:before{content:"\F09B"}.van-icon-photo-o:before{content:"\F09C"}.van-icon-photo:before{content:"\F09D"}.van-icon-photograph:before{content:"\F09E"}.van-icon-play-circle-o:before{content:"\F09F"}.van-icon-play-circle:before{content:"\F0A0"}.van-icon-play:before{content:"\F0A1"}.van-icon-plus:before{content:"\F0A2"}.van-icon-point-gift-o:before{content:"\F0A3"}.van-icon-point-gift:before{content:"\F0A4"}.van-icon-points:before{content:"\F0A5"}.van-icon-printer:before{content:"\F0A6"}.van-icon-qr-invalid:before{content:"\F0A7"}.van-icon-qr:before{content:"\F0A8"}.van-icon-question-o:before{content:"\F0A9"}.van-icon-question:before{content:"\F0AA"}.van-icon-records:before{content:"\F0AB"}.van-icon-refund-o:before{content:"\F0AC"}.van-icon-replay:before{content:"\F0AD"}.van-icon-scan:before{content:"\F0AE"}.van-icon-search:before{content:"\F0AF"}.van-icon-send-gift-o:before{content:"\F0B0"}.van-icon-send-gift:before{content:"\F0B1"}.van-icon-service-o:before{content:"\F0B2"}.van-icon-service:before{content:"\F0B3"}.van-icon-setting-o:before{content:"\F0B4"}.van-icon-setting:before{content:"\F0B5"}.van-icon-share:before{content:"\F0B6"}.van-icon-shop-collect-o:before{content:"\F0B7"}.van-icon-shop-collect:before{content:"\F0B8"}.van-icon-shop-o:before{content:"\F0B9"}.van-icon-shop:before{content:"\F0BA"}.van-icon-shopping-cart-o:before{content:"\F0BB"}.van-icon-shopping-cart:before{content:"\F0BC"}.van-icon-shrink:before{content:"\F0BD"}.van-icon-sign:before{content:"\F0BE"}.van-icon-smile-comment-o:before{content:"\F0BF"}.van-icon-smile-comment:before{content:"\F0C0"}.van-icon-smile-o:before{content:"\F0C1"}.van-icon-smile:before{content:"\F0C2"}.van-icon-star-o:before{content:"\F0C3"}.van-icon-star:before{content:"\F0C4"}.van-icon-stop-circle-o:before{content:"\F0C5"}.van-icon-stop-circle:before{content:"\F0C6"}.van-icon-stop:before{content:"\F0C7"}.van-icon-success:before{content:"\F0C8"}.van-icon-thumb-circle-o:before{content:"\F0C9"}.van-icon-thumb-circle:before{content:"\F0CA"}.van-icon-todo-list-o:before{content:"\F0CB"}.van-icon-todo-list:before{content:"\F0CC"}.van-icon-tosend:before{content:"\F0CD"}.van-icon-tv-o:before{content:"\F0CE"}.van-icon-umbrella-circle:before{content:"\F0CF"}.van-icon-underway-o:before{content:"\F0D0"}.van-icon-underway:before{content:"\F0D1"}.van-icon-upgrade:before{content:"\F0D2"}.van-icon-user-circle-o:before{content:"\F0D3"}.van-icon-user-o:before{content:"\F0D4"}.van-icon-video-o:before{content:"\F0D5"}.van-icon-video:before{content:"\F0D6"}.van-icon-vip-card-o:before{content:"\F0D7"}.van-icon-vip-card:before{content:"\F0D8"}.van-icon-volume-o:before{content:"\F0D9"}.van-icon-volume:before{content:"\F0DA"}.van-icon-wap-home-o:before{content:"\F0DB"}.van-icon-wap-home:before{content:"\F0DC"}.van-icon-wap-nav:before{content:"\F0DD"}.van-icon-warn-o:before{content:"\F0DE"}.van-icon-warning-o:before{content:"\F0DF"}.van-icon-warning:before{content:"\F0E0"}.van-icon-weapp-nav:before{content:"\F0E1"}.van-icon-wechat:before{content:"\F0E2"}.van-icon-youzan-shield:before{content:"\F0E3"}:host{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-icon--image{width:1em;height:1em}.van-icon__image{width:100%;height:100%}.van-icon__info{z-index:1}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { addUnit, isDef } from '../common/utils';
2 import { VantComponent } from '../common/component';
3 import { button } from '../mixins/button';
4 import { openType } from '../mixins/open-type';
5 VantComponent({
6 mixins: [button, openType],
7 classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
8 props: {
9 src: String,
10 width: String,
11 height: String,
12 fit: {
13 type: String,
14 value: 'fill'
15 },
16 round: Boolean,
17 lazyLoad: Boolean,
18 showError: {
19 type: Boolean,
20 value: true
21 },
22 showLoading: {
23 type: Boolean,
24 value: true
25 },
26 showMenuByLongpress: Boolean,
27 // 受小程序slot限制所需要的属性
28 useLoadingSlot: Boolean,
29 useErrorSlot: Boolean,
30 },
31 data: {
32 fitWeapp: 'aspectFit',
33 FIT_MODE_MAP: {
34 contain: 'aspectFit',
35 cover: 'aspectFill',
36 fill: 'scaleToFill',
37 none: 'center',
38 // TODO: 这个没有原生的属性,需要后面实现,暂时先用contain;
39 'scale-down': 'aspectFit'
40 },
41 loading: true,
42 error: false
43 },
44 watch: {
45 src() {
46 this.setData({
47 loading: true,
48 error: false
49 });
50 }
51 },
52 mounted() {
53 this.init();
54 },
55 methods: {
56 init() {
57 const { FIT_MODE_MAP, fit } = this.data;
58 this.setData({
59 mode: FIT_MODE_MAP[fit],
60 style: this.getStyle(),
61 });
62 },
63 getStyle() {
64 const { width, height } = this.data;
65 let style = '';
66 if (isDef(width)) {
67 style += `width: ${addUnit(width)};`;
68 }
69 if (isDef(height)) {
70 style += `height: ${addUnit(height)};`;
71 }
72 return style;
73 },
74 onLoad(event) {
75 this.setData({
76 loading: false
77 });
78 this.$emit('load', event.detail);
79 },
80 onError(event) {
81 this.setData({
82 loading: false,
83 error: true,
84 });
85 this.$emit('error', event.detail);
86 },
87 onClick(event) {
88 this.$emit('click', event.detail);
89 },
90 }
91 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-loading": "../loading/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('image', { round })}}"
5 style="{{ style }}"
6 bind:tap="onClick"
7 >
8 <image
9 wx:if="{{ !error }}"
10 class="image-class van-image__img"
11 mode="{{ mode }}"
12 src="{{ src }}"
13 lazy-load="{{ lazyLoad }}"
14 show-menu-by-longpress="{{ showMenuByLongpress }}"
15 bind:load="onLoad"
16 bind:error="onError"
17 />
18
19 <view
20 wx:if="{{ loading && showLoading }}"
21 class="loading-class van-image__loading"
22 >
23 <slot
24 wx:if="{{ useLoadingSlot }}"
25 name="loading"
26 />
27 <van-icon
28 wx:else
29 name="photo-o"
30 size="22"
31 />
32 </view>
33 <view
34 wx:if="{{ error && showError }}"
35 class="error-class van-image__error"
36 >
37 <slot
38 wx:if="{{ useErrorSlot }}"
39 name="error"
40 />
41 <van-icon
42 wx:else
43 name="warning-o"
44 size="22"
45 />
46 </view>
47 </view>
1 @import '../common/index.wxss';.van-image{position:relative;display:inline-block}.van-image--round{overflow:hidden;border-radius:50%}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;width:100%;height:100%}.van-image__error,.van-image__loading{position:absolute;top:0;left:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#969799;color:var(--image-placeholder-text-color,#969799);font-size:14px;font-size:var(--image-placeholder-font-size,14px);background-color:#f8f8f8;background-color:var(--image-placeholder-background-color,#f8f8f8)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'index-bar',
5 type: 'ancestor',
6 linked(target) {
7 this.parent = target;
8 },
9 unlinked() {
10 this.parent = null;
11 }
12 },
13 props: {
14 useSlot: Boolean,
15 index: null
16 },
17 data: {
18 active: false,
19 wrapperStyle: '',
20 anchorStyle: ''
21 }
22 });
1 <view
2 class="van-index-anchor-wrapper"
3 style="{{ wrapperStyle }}"
4 >
5 <view
6 class="van-index-anchor {{ active ? 'van-index-anchor--active van-hairline--bottom' : '' }}"
7 style="{{ anchorStyle }}"
8 >
9 <slot wx:if="{{ useSlot }}"/>
10 <block wx:else>
11 <text>{{ index }}</text>
12 </block>
13 </view>
14 </view>
1 @import '../common/index.wxss';.van-index-anchor{padding:0 16px;padding:var(--index-anchor-padding,0 16px);color:#323233;color:var(--index-anchor-text-color,#323233);font-weight:500;font-weight:var(--index-anchor-font-weight,500);font-size:14px;font-size:var(--index-anchor-font-size,14px);line-height:32px;line-height:var(--index-anchor-line-height,32px);background-color:initial;background-color:var(--index-anchor-background-color,transparent)}.van-index-anchor--active{right:0;left:0;color:#07c160;color:var(--index-anchor-active-text-color,#07c160);background-color:#fff;background-color:var(--index-anchor-active-background-color,#fff)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { GREEN } from '../common/color';
3 const indexList = () => {
4 const indexList = [];
5 const charCodeOfA = 'A'.charCodeAt(0);
6 for (let i = 0; i < 26; i++) {
7 indexList.push(String.fromCharCode(charCodeOfA + i));
8 }
9 return indexList;
10 };
11 VantComponent({
12 relation: {
13 name: 'index-anchor',
14 type: 'descendant',
15 linked() {
16 this.updateData();
17 },
18 linkChanged() {
19 this.updateData();
20 },
21 unlinked() {
22 this.updateData();
23 }
24 },
25 props: {
26 sticky: {
27 type: Boolean,
28 value: true
29 },
30 zIndex: {
31 type: Number,
32 value: 1
33 },
34 highlightColor: {
35 type: String,
36 value: GREEN
37 },
38 scrollTop: {
39 type: Number,
40 value: 0,
41 observer: 'onScroll'
42 },
43 stickyOffsetTop: {
44 type: Number,
45 value: 0
46 },
47 indexList: {
48 type: Array,
49 value: indexList()
50 }
51 },
52 data: {
53 activeAnchorIndex: null,
54 showSidebar: false
55 },
56 methods: {
57 updateData() {
58 this.timer && clearTimeout(this.timer);
59 this.timer = setTimeout(() => {
60 this.children = this.getRelationNodes('../index-anchor/index');
61 this.setData({
62 showSidebar: !!this.children.length
63 });
64 this.setRect().then(() => {
65 this.onScroll();
66 });
67 }, 0);
68 },
69 setRect() {
70 return Promise.all([
71 this.setAnchorsRect(),
72 this.setListRect(),
73 this.setSiderbarRect()
74 ]);
75 },
76 setAnchorsRect() {
77 return Promise.all(this.children.map(anchor => (anchor.getRect('.van-index-anchor-wrapper').then((rect) => {
78 Object.assign(anchor, {
79 height: rect.height,
80 top: rect.top + this.data.scrollTop
81 });
82 }))));
83 },
84 setListRect() {
85 return this.getRect('.van-index-bar').then((rect) => {
86 Object.assign(this, {
87 height: rect.height,
88 top: rect.top + this.data.scrollTop
89 });
90 });
91 },
92 setSiderbarRect() {
93 return this.getRect('.van-index-bar__sidebar').then(res => {
94 this.sidebar = {
95 height: res.height,
96 top: res.top
97 };
98 });
99 },
100 setDiffData({ target, data }) {
101 const diffData = {};
102 Object.keys(data).forEach(key => {
103 if (target.data[key] !== data[key]) {
104 diffData[key] = data[key];
105 }
106 });
107 if (Object.keys(diffData).length) {
108 target.setData(diffData);
109 }
110 },
111 getAnchorRect(anchor) {
112 return anchor.getRect('.van-index-anchor-wrapper').then((rect) => ({
113 height: rect.height,
114 top: rect.top
115 }));
116 },
117 getActiveAnchorIndex() {
118 const { children } = this;
119 const { sticky, scrollTop, stickyOffsetTop } = this.data;
120 for (let i = this.children.length - 1; i >= 0; i--) {
121 const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
122 const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
123 if (reachTop + scrollTop >= children[i].top) {
124 return i;
125 }
126 }
127 return -1;
128 },
129 onScroll() {
130 const { children = [] } = this;
131 if (!children.length) {
132 return;
133 }
134 const { sticky, stickyOffsetTop, zIndex, highlightColor, scrollTop } = this.data;
135 const active = this.getActiveAnchorIndex();
136 this.setDiffData({
137 target: this,
138 data: {
139 activeAnchorIndex: active
140 }
141 });
142 if (sticky) {
143 let isActiveAnchorSticky = false;
144 if (active !== -1) {
145 isActiveAnchorSticky = children[active].top <= stickyOffsetTop + scrollTop;
146 }
147 children.forEach((item, index) => {
148 if (index === active) {
149 let wrapperStyle = '';
150 let anchorStyle = `
151 color: ${highlightColor};
152 `;
153 if (isActiveAnchorSticky) {
154 wrapperStyle = `
155 height: ${children[index].height}px;
156 `;
157 anchorStyle = `
158 position: fixed;
159 top: ${stickyOffsetTop}px;
160 z-index: ${zIndex};
161 color: ${highlightColor};
162 `;
163 }
164 this.setDiffData({
165 target: item,
166 data: {
167 active: true,
168 anchorStyle,
169 wrapperStyle
170 }
171 });
172 }
173 else if (index === active - 1) {
174 const currentAnchor = children[index];
175 const currentOffsetTop = currentAnchor.top;
176 const targetOffsetTop = index === children.length - 1
177 ? this.top
178 : children[index + 1].top;
179 const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
180 const translateY = parentOffsetHeight - currentAnchor.height;
181 const anchorStyle = `
182 position: relative;
183 transform: translate3d(0, ${translateY}px, 0);
184 z-index: ${zIndex};
185 color: ${highlightColor};
186 `;
187 this.setDiffData({
188 target: item,
189 data: {
190 active: true,
191 anchorStyle
192 }
193 });
194 }
195 else {
196 this.setDiffData({
197 target: item,
198 data: {
199 active: false,
200 anchorStyle: '',
201 wrapperStyle: '',
202 }
203 });
204 }
205 });
206 }
207 },
208 onClick(event) {
209 this.scrollToAnchor(event.target.dataset.index);
210 },
211 onTouchMove(event) {
212 const sidebarLength = this.children.length;
213 const touch = event.touches[0];
214 const itemHeight = this.sidebar.height / sidebarLength;
215 let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
216 if (index < 0) {
217 index = 0;
218 }
219 else if (index > sidebarLength - 1) {
220 index = sidebarLength - 1;
221 }
222 this.scrollToAnchor(index);
223 },
224 onTouchStop() {
225 this.scrollToAnchorIndex = null;
226 },
227 scrollToAnchor(index) {
228 if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
229 return;
230 }
231 this.scrollToAnchorIndex = index;
232 const anchor = this.children.filter(item => item.data.index === this.data.indexList[index])[0];
233 this.$emit('select', anchor.data.index);
234 anchor && wx.pageScrollTo({
235 duration: 0,
236 scrollTop: anchor.top
237 });
238 }
239 }
240 });
1 <view class="van-index-bar">
2 <slot />
3
4 <view
5 wx:if="{{ showSidebar }}"
6 class="van-index-bar__sidebar"
7 catch:tap="onClick"
8 catch:touchmove="onTouchMove"
9 catch:touchend="onTouchStop"
10 catch:touchcancel="onTouchStop"
11 >
12 <view
13 wx:for="{{ indexList }}"
14 wx:key="index"
15 class="van-index-bar__index"
16 style="z-index: {{ zIndex + 1 }}; color: {{ activeAnchorIndex === index ? highlightColor : '' }}"
17 data-index="{{ index }}"
18 >
19 {{ item }}
20 </view>
21 </view>
22 </view>
1 @import '../common/index.wxss';.van-index-bar{position:relative}.van-index-bar__sidebar{position:fixed;top:50%;right:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;text-align:center;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-weight:500;padding:0 4px 0 16px;padding:0 var(--padding-base,4px) 0 var(--padding-md,16px);font-size:10px;font-size:var(--index-bar-index-font-size,10px);line-height:14px;line-height:var(--index-bar-index-line-height,14px)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 VantComponent({ 2 VantComponent({
3 props: { 3 props: {
4 dot: Boolean,
4 info: null, 5 info: null,
5 customStyle: String 6 customStyle: String
6 } 7 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
1 <view 3 <view
2 wx:if="{{ info !== null }}" 4 wx:if="{{ info !== null && info !== '' || dot }}"
3 class="custom-class van-info" 5 class="custom-class van-info {{ utils.bem('info', { dot }) }}"
4 style="{{ customStyle }}" 6 style="{{ customStyle }}"
5 >{{ info }}</view> 7 >{{ dot ? '' : info }}</view>
......
1 @import '../common/index.wxss';.van-info{position:absolute;top:-8px;right:0;min-width:16px;padding:0 3px;font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:12px;font-weight:500;line-height:14px;color:#fff;text-align:center;white-space:nowrap;background-color:#f44;border:1px solid #fff;border-radius:16px;-webkit-transform:translateX(50%);transform:translateX(50%);box-sizing:border-box;-webkit-transform-origin:100%;transform-origin:100%}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-info{position:absolute;top:0;right:0;box-sizing:border-box;white-space:nowrap;text-align:center;-webkit-transform:translate(50%,-50%);transform:translate(50%,-50%);-webkit-transform-origin:100%;transform-origin:100%;min-width:16px;min-width:var(--info-size,16px);padding:0 3px;padding:var(--info-padding,0 3px);color:#fff;color:var(--info-color,#fff);font-weight:500;font-weight:var(--info-font-weight,500);font-size:12px;font-size:var(--info-font-size,12px);font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--info-font-family,PingFang SC,Helvetica Neue,Arial,sans-serif);line-height:14px;line-height:calc(var(--info-size, 16px) - var(--info-border-width, 1px)*2);background-color:#ee0a24;background-color:var(--info-background-color,#ee0a24);border:1px solid #fff;border:var(--info-border-width,1px) solid var(--white,#fff);border-radius:16px;border-radius:var(--info-size,16px)}.van-info--dot{min-width:0;border-radius:100%;width:8px;width:var(--info-dot-size,8px);height:8px;height:var(--info-dot-size,8px);background-color:#ee0a24;background-color:var(--info-dot-color,#ee0a24)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { addUnit } from '../common/utils';
2 VantComponent({ 3 VantComponent({
3 props: { 4 props: {
4 size: { 5 color: String,
5 type: String, 6 vertical: Boolean,
6 value: '30px'
7 },
8 type: { 7 type: {
9 type: String, 8 type: String,
10 value: 'circular' 9 value: 'circular'
11 }, 10 },
12 color: { 11 size: {
12 type: String,
13 observer: 'setSizeWithUnit'
14 },
15 textSize: {
13 type: String, 16 type: String,
14 value: '#c9c9c9' 17 observer: 'setTextSizeWithUnit'
18 }
19 },
20 methods: {
21 setSizeWithUnit(size) {
22 this.setData({
23 sizeWithUnit: addUnit(size)
24 });
25 },
26 setTextSizeWithUnit(size) {
27 this.set({
28 textSizeWithUnit: addUnit(size)
29 });
15 } 30 }
16 } 31 }
17 }); 32 });
......
1 <view 1 <view class="custom-class van-loading {{ vertical ? 'van-loading--vertical' : '' }}">
2 class="van-loading custom-class"
3 style="width: {{ size }}; height: {{ size }}"
4 >
5 <view 2 <view
6 class="van-loading__spinner van-loading__spinner--{{ type }}" 3 class="van-loading__spinner van-loading__spinner--{{ type }}"
7 style="color: {{ color }};" 4 style="color: {{ color }}; width: {{ sizeWithUnit }}; height: {{ sizeWithUnit }}"
8 > 5 >
9 <view 6 <view
10 wx:if="{{ type === 'spinner' }}" 7 wx:if="{{ type === 'spinner' }}"
...@@ -13,4 +10,7 @@ ...@@ -13,4 +10,7 @@
13 class="van-loading__dot" 10 class="van-loading__dot"
14 /> 11 />
15 </view> 12 </view>
13 <view class="van-loading__text" style="font-size: {{ textSizeWithUnit }};">
14 <slot />
15 </view>
16 </view> 16 </view>
......
1 @import '../common/index.wxss';.van-loading{z-index:0;line-height:0;vertical-align:middle}.van-loading,.van-loading__spinner{position:relative;display:inline-block}.van-loading__spinner{z-index:-1;width:100%;height:100%;box-sizing:border-box;-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border-radius:100%;border:1px solid transparent;border-top-color:initial}.van-loading__dot{top:0;left:0;width:100%;height:100%;position:absolute}.van-loading__dot:before{width:2px;height:25%;content:" ";display:block;margin:0 auto;border-radius:40%;background-color:currentColor}.van-loading__dot:first-of-type{opacity:1;-webkit-transform:rotate(30deg);transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;-webkit-transform:rotate(60deg);transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;-webkit-transform:rotate(120deg);transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;-webkit-transform:rotate(150deg);transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;-webkit-transform:rotate(210deg);transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;-webkit-transform:rotate(240deg);transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;-webkit-transform:rotate(300deg);transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;-webkit-transform:rotate(330deg);transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;-webkit-transform:rotate(1turn);transform:rotate(1turn)}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#c8c9cc;color:var(--loading-spinner-color,#c8c9cc)}.van-loading__spinner{position:relative;box-sizing:border-box;width:30px;width:var(--loading-spinner-size,30px);max-width:100%;max-height:100%;height:30px;height:var(--loading-spinner-size,30px);-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite;-webkit-animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-top-color:initial;border-radius:100%}.van-loading__text{margin-left:8px;margin-left:var(--padding-xs,8px);color:#969799;color:var(--loading-text-color,#969799);font-size:14px;font-size:var(--loading-text-font-size,14px);line-height:20px;line-height:var(--loading-text-line-height,20px)}.van-loading__text:empty{display:none}.van-loading--vertical{-webkit-flex-direction:column;flex-direction:column}.van-loading--vertical .van-loading__text{margin:8px 0 0;margin:var(--padding-xs,8px) 0 0}.van-loading__dot{position:absolute;top:0;left:0;width:100%;height:100%}.van-loading__dot:before{display:block;width:2px;height:25%;margin:0 auto;background-color:currentColor;border-radius:40%;content:" "}.van-loading__dot:first-of-type{-webkit-transform:rotate(30deg);transform:rotate(30deg);opacity:1}.van-loading__dot:nth-of-type(2){-webkit-transform:rotate(60deg);transform:rotate(60deg);opacity:.9375}.van-loading__dot:nth-of-type(3){-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:.875}.van-loading__dot:nth-of-type(4){-webkit-transform:rotate(120deg);transform:rotate(120deg);opacity:.8125}.van-loading__dot:nth-of-type(5){-webkit-transform:rotate(150deg);transform:rotate(150deg);opacity:.75}.van-loading__dot:nth-of-type(6){-webkit-transform:rotate(180deg);transform:rotate(180deg);opacity:.6875}.van-loading__dot:nth-of-type(7){-webkit-transform:rotate(210deg);transform:rotate(210deg);opacity:.625}.van-loading__dot:nth-of-type(8){-webkit-transform:rotate(240deg);transform:rotate(240deg);opacity:.5625}.van-loading__dot:nth-of-type(9){-webkit-transform:rotate(270deg);transform:rotate(270deg);opacity:.5}.van-loading__dot:nth-of-type(10){-webkit-transform:rotate(300deg);transform:rotate(300deg);opacity:.4375}.van-loading__dot:nth-of-type(11){-webkit-transform:rotate(330deg);transform:rotate(330deg);opacity:.375}.van-loading__dot:nth-of-type(12){-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:.3125}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
...\ No newline at end of file ...\ No newline at end of file
......
1 export declare const basic: void; 1 export declare const basic: string;
......
1 export const basic = Behavior({ 1 export const basic = Behavior({
2 methods: { 2 methods: {
3 $emit() { 3 $emit(...args) {
4 this.triggerEvent.apply(this, arguments); 4 this.triggerEvent(...args);
5 }, 5 },
6 getRect(selector, all) { 6 getRect(selector, all) {
7 return new Promise(resolve => { 7 return new Promise(resolve => {
......
1 export declare const button: void; 1 export declare const button: string;
......
1 export declare const link: void; 1 export declare const link: string;
......
1 export declare const behavior: void; 1 export declare const behavior: string;
......
1 function setAsync(context, data) {
2 return new Promise(resolve => {
3 context.setData(data, resolve);
4 });
5 }
6 ;
7 export const behavior = Behavior({ 1 export const behavior = Behavior({
8 created() {
9 if (!this.$options) {
10 return;
11 }
12 const cache = {};
13 const { computed } = this.$options();
14 const keys = Object.keys(computed);
15 this.calcComputed = () => {
16 const needUpdate = {};
17 keys.forEach(key => {
18 const value = computed[key].call(this);
19 if (cache[key] !== value) {
20 cache[key] = needUpdate[key] = value;
21 }
22 });
23 return needUpdate;
24 };
25 },
26 attached() {
27 this.set();
28 },
29 methods: { 2 methods: {
30 // set data and set computed data
31 set(data, callback) { 3 set(data, callback) {
32 const stack = []; 4 return new Promise(resolve => {
33 if (data) { 5 this.setData(data, () => {
34 stack.push(setAsync(this, data)); 6 if (callback && typeof callback === 'function') {
35 } 7 callback.call(this);
36 if (this.calcComputed) { 8 }
37 stack.push(setAsync(this, this.calcComputed())); 9 resolve();
38 } 10 });
39 return Promise.all(stack).then(res => {
40 if (callback && typeof callback === 'function') {
41 callback.call(this);
42 }
43 return res;
44 }); 11 });
45 } 12 }
46 } 13 }
......
1 import { behavior } from './behavior'; 1 import { behavior } from './behavior';
2 import { observeProps } from './props';
3 export function observe(vantOptions, options) { 2 export function observe(vantOptions, options) {
4 const { watch, computed } = vantOptions; 3 const { watch } = vantOptions;
5 options.behaviors.push(behavior); 4 options.behaviors.push(behavior);
6 if (watch) { 5 if (watch) {
7 const props = options.properties || {}; 6 const props = options.properties || {};
...@@ -17,11 +16,4 @@ export function observe(vantOptions, options) { ...@@ -17,11 +16,4 @@ export function observe(vantOptions, options) {
17 }); 16 });
18 options.properties = props; 17 options.properties = props;
19 } 18 }
20 if (computed) {
21 options.methods = options.methods || {};
22 options.methods.$options = () => vantOptions;
23 if (options.properties) {
24 observeProps(options.properties);
25 }
26 }
27 } 19 }
......
1 export declare function observeProps(props: any): void;
1 export function observeProps(props) {
2 if (!props) {
3 return;
4 }
5 Object.keys(props).forEach(key => {
6 let prop = props[key];
7 if (prop === null || !('type' in prop)) {
8 prop = { type: prop };
9 }
10 let { observer } = prop;
11 prop.observer = function () {
12 if (observer) {
13 if (typeof observer === 'string') {
14 observer = this[observer];
15 }
16 observer.apply(this, arguments);
17 }
18 this.set();
19 };
20 props[key] = prop;
21 });
22 }
1 export declare const openType: void; 1 export declare const openType: string;
......
1 export declare const safeArea: ({ safeAreaInsetBottom, safeAreaInsetTop }?: {
2 safeAreaInsetBottom?: boolean;
3 safeAreaInsetTop?: boolean;
4 }) => void;
1 let cache = null;
2 function getSafeArea() {
3 return new Promise((resolve, reject) => {
4 if (cache != null) {
5 resolve(cache);
6 }
7 else {
8 wx.getSystemInfo({
9 success: ({ model, screenHeight, statusBarHeight }) => {
10 const iphoneX = /iphone x/i.test(model);
11 const iphoneNew = /iPhone11/i.test(model) && screenHeight === 812;
12 cache = {
13 isIPhoneX: iphoneX || iphoneNew,
14 statusBarHeight
15 };
16 resolve(cache);
17 },
18 fail: reject
19 });
20 }
21 });
22 }
23 export const safeArea = ({ safeAreaInsetBottom = true, safeAreaInsetTop = false } = {}) => Behavior({
24 properties: {
25 safeAreaInsetTop: {
26 type: Boolean,
27 value: safeAreaInsetTop
28 },
29 safeAreaInsetBottom: {
30 type: Boolean,
31 value: safeAreaInsetBottom
32 }
33 },
34 created() {
35 getSafeArea().then(({ isIPhoneX, statusBarHeight }) => {
36 this.set({ isIPhoneX, statusBarHeight });
37 });
38 }
39 });
1 export declare const touch: void; 1 export declare const touch: string;
......
1 export declare const transition: (showDefaultValue: boolean) => void; 1 export declare const transition: (showDefaultValue: boolean) => any;
......
...@@ -10,85 +10,109 @@ export const transition = function (showDefaultValue) { ...@@ -10,85 +10,109 @@ export const transition = function (showDefaultValue) {
10 return Behavior({ 10 return Behavior({
11 properties: { 11 properties: {
12 customStyle: String, 12 customStyle: String,
13 // @ts-ignore
13 show: { 14 show: {
14 type: Boolean, 15 type: Boolean,
15 value: showDefaultValue, 16 value: showDefaultValue,
16 observer: 'observeShow' 17 observer: 'observeShow'
17 }, 18 },
19 // @ts-ignore
18 duration: { 20 duration: {
19 type: [Number, Object], 21 type: null,
20 value: 300, 22 value: 300,
21 observer: 'observeDuration' 23 observer: 'observeDuration'
22 }, 24 },
23 name: { 25 name: {
24 type: String, 26 type: String,
25 value: 'fade', 27 value: 'fade'
26 observer: 'updateClasses'
27 } 28 }
28 }, 29 },
29 data: { 30 data: {
30 type: '', 31 type: '',
31 inited: false, 32 inited: false,
32 display: false, 33 display: false
33 classNames: getClassNames('fade')
34 }, 34 },
35 attached() { 35 attached() {
36 if (this.data.show) { 36 if (this.data.show) {
37 this.show(); 37 this.enter();
38 } 38 }
39 }, 39 },
40 methods: { 40 methods: {
41 observeShow(value) { 41 observeShow(value) {
42 if (value) { 42 value ? this.enter() : this.leave();
43 this.show();
44 }
45 else {
46 this.leave();
47 }
48 },
49 updateClasses(name) {
50 this.set({
51 classNames: getClassNames(name)
52 });
53 }, 43 },
54 show() { 44 enter() {
55 const { classNames, duration } = this.data; 45 const { duration, name } = this.data;
56 const currentDuration = isObj(duration) ? duration.leave : duration; 46 const classNames = getClassNames(name);
47 const currentDuration = isObj(duration) ? duration.enter : duration;
48 this.status = 'enter';
49 this.$emit('before-enter');
57 Promise.resolve() 50 Promise.resolve()
58 .then(nextTick) 51 .then(nextTick)
59 .then(() => this.set({ 52 .then(() => {
60 inited: true, 53 this.checkStatus('enter');
61 display: true, 54 this.$emit('enter');
62 classes: classNames.enter, 55 this.setData({
63 currentDuration 56 inited: true,
64 })) 57 display: true,
58 classes: classNames.enter,
59 currentDuration
60 });
61 })
65 .then(nextTick) 62 .then(nextTick)
66 .then(() => this.set({ 63 .then(() => {
67 classes: classNames['enter-to'] 64 this.checkStatus('enter');
68 })); 65 this.transitionEnded = false;
66 this.setData({
67 classes: classNames['enter-to']
68 });
69 })
70 .catch(() => { });
69 }, 71 },
70 leave() { 72 leave() {
71 const { classNames, duration } = this.data; 73 if (!this.data.display) {
72 const currentDuration = isObj(duration) ? duration.leave : duration;
73 if (+currentDuration === 0) {
74 this.onTransitionEnd();
75 return; 74 return;
76 } 75 }
76 const { duration, name } = this.data;
77 const classNames = getClassNames(name);
78 const currentDuration = isObj(duration) ? duration.leave : duration;
79 this.status = 'leave';
80 this.$emit('before-leave');
77 Promise.resolve() 81 Promise.resolve()
78 .then(nextTick) 82 .then(nextTick)
79 .then(() => this.set({ 83 .then(() => {
80 classes: classNames.leave, 84 this.checkStatus('leave');
81 currentDuration 85 this.$emit('leave');
82 })) 86 this.setData({
87 classes: classNames.leave,
88 currentDuration
89 });
90 })
83 .then(nextTick) 91 .then(nextTick)
84 .then(() => this.set({ 92 .then(() => {
85 classes: classNames['leave-to'] 93 this.checkStatus('leave');
86 })); 94 this.transitionEnded = false;
95 setTimeout(() => this.onTransitionEnd(), currentDuration);
96 this.setData({
97 classes: classNames['leave-to']
98 });
99 })
100 .catch(() => { });
101 },
102 checkStatus(status) {
103 if (status !== this.status) {
104 throw new Error(`incongruent status: ${status}`);
105 }
87 }, 106 },
88 onTransitionEnd() { 107 onTransitionEnd() {
89 if (!this.data.show) { 108 if (this.transitionEnded) {
90 this.set({ display: false }); 109 return;
91 this.$emit('transitionEnd'); 110 }
111 this.transitionEnded = true;
112 this.$emit(`after-${this.status}`);
113 const { show, display } = this.data;
114 if (!show && display) {
115 this.setData({ display: false });
92 } 116 }
93 } 117 }
94 } 118 }
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({ 2 VantComponent({
4 mixins: [safeArea({ safeAreaInsetTop: true })],
5 classes: ['title-class'], 3 classes: ['title-class'],
6 props: { 4 props: {
7 title: String, 5 title: String,
...@@ -15,8 +13,19 @@ VantComponent({ ...@@ -15,8 +13,19 @@ VantComponent({
15 }, 13 },
16 zIndex: { 14 zIndex: {
17 type: Number, 15 type: Number,
18 value: 120 16 value: 1
19 } 17 },
18 safeAreaInsetTop: {
19 type: Boolean,
20 value: true
21 },
22 },
23 data: {
24 statusBarHeight: 0
25 },
26 created() {
27 const { statusBarHeight } = wx.getSystemInfoSync();
28 this.setData({ statusBarHeight });
20 }, 29 },
21 methods: { 30 methods: {
22 onClickLeft() { 31 onClickLeft() {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 <view 3 <view
4 class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}" 4 class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
5 style="z-index: {{ zIndex }}; {{ safeAreaInsetTop ? 'padding-top: ' + statusBarHeight + 'px;' : '' }}" 5 style="z-index: {{ zIndex }}; padding-top: {{ safeAreaInsetTop ? statusBarHeight : 0 }}px;"
6 > 6 >
7 <view class="van-nav-bar__left" bind:tap="onClickLeft"> 7 <view class="van-nav-bar__left" bind:tap="onClickLeft">
8 <block wx:if="{{ leftArrow || leftText }}"> 8 <block wx:if="{{ leftArrow || leftText }}">
......
1 @import '../common/index.wxss';.van-nav-bar{position:relative;height:44px;line-height:44px;text-align:center;background-color:#fff;-webkit-user-select:none;user-select:none}.van-nav-bar__text{display:inline-block;padding:0 15px;margin:0 -15px;color:#1989fa;vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:#1989fa;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{padding-left:25px;margin-left:-20px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;font-size:16px;font-weight:500}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px}.van-nav-bar__left{left:15px}.van-nav-bar__right{right:15px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-nav-bar{position:relative;text-align:center;-webkit-user-select:none;user-select:none;height:44px;height:var(--nav-bar-height,44px);line-height:44px;line-height:var(--nav-bar-height,44px);background-color:#fff;background-color:var(--nav-bar-background-color,#fff)}.van-nav-bar__text{display:inline-block;vertical-align:middle;margin:0 -16px;margin:0 -var(--padding-md,16px);padding:0 16px;padding:0 var(--padding-md,16px);color:#1989fa;color:var(--nav-bar-text-color,#1989fa)}.van-nav-bar__text--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-nav-bar__arrow{vertical-align:middle;font-size:16px;font-size:var(--nav-bar-arrow-size,16px);color:#1989fa;color:var(--nav-bar-text-color,#1989fa)}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;color:#323233;color:var(--nav-bar-title-text-color,#323233);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--nav-bar-title-font-size,16px)}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px;font-size:var(--font-size-md,14px)}.van-nav-bar__left{left:16px;left:var(--padding-md,16px)}.van-nav-bar__right{right:16px;right:var(--padding-md,16px)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -21,7 +21,7 @@ VantComponent({ ...@@ -21,7 +21,7 @@ VantComponent({
21 }, 21 },
22 delay: { 22 delay: {
23 type: Number, 23 type: Number,
24 value: 0 24 value: 1
25 }, 25 },
26 speed: { 26 speed: {
27 type: Number, 27 type: Number,
...@@ -42,23 +42,18 @@ VantComponent({ ...@@ -42,23 +42,18 @@ VantComponent({
42 backgroundColor: { 42 backgroundColor: {
43 type: String, 43 type: String,
44 value: BG_COLOR 44 value: BG_COLOR
45 } 45 },
46 wrapable: Boolean
46 }, 47 },
47 data: { 48 data: {
48 show: true, 49 show: true
49 hasRightIcon: false
50 }, 50 },
51 watch: { 51 watch: {
52 text() { 52 text() {
53 this.set({}, this.init); 53 this.setData({}, this.init);
54 } 54 }
55 }, 55 },
56 created() { 56 created() {
57 if (this.data.mode) {
58 this.set({
59 hasRightIcon: true
60 });
61 }
62 this.resetAnimation = wx.createAnimation({ 57 this.resetAnimation = wx.createAnimation({
63 duration: 0, 58 duration: 0,
64 timingFunction: 'linear' 59 timingFunction: 'linear'
...@@ -71,7 +66,7 @@ VantComponent({ ...@@ -71,7 +66,7 @@ VantComponent({
71 init() { 66 init() {
72 Promise.all([ 67 Promise.all([
73 this.getRect('.van-notice-bar__content'), 68 this.getRect('.van-notice-bar__content'),
74 this.getRect('.van-notice-bar__content-wrap') 69 this.getRect('.van-notice-bar__wrap')
75 ]).then((rects) => { 70 ]).then((rects) => {
76 const [contentRect, wrapRect] = rects; 71 const [contentRect, wrapRect] = rects;
77 if (contentRect == null || 72 if (contentRect == null ||
...@@ -98,14 +93,14 @@ VantComponent({ ...@@ -98,14 +93,14 @@ VantComponent({
98 scroll() { 93 scroll() {
99 this.timer && clearTimeout(this.timer); 94 this.timer && clearTimeout(this.timer);
100 this.timer = null; 95 this.timer = null;
101 this.set({ 96 this.setData({
102 animationData: this.resetAnimation 97 animationData: this.resetAnimation
103 .translateX(this.wrapWidth) 98 .translateX(this.wrapWidth)
104 .step() 99 .step()
105 .export() 100 .export()
106 }); 101 });
107 setTimeout(() => { 102 setTimeout(() => {
108 this.set({ 103 this.setData({
109 animationData: this.animation 104 animationData: this.animation
110 .translateX(-this.contentWidth) 105 .translateX(-this.contentWidth)
111 .step() 106 .step()
...@@ -119,7 +114,7 @@ VantComponent({ ...@@ -119,7 +114,7 @@ VantComponent({
119 onClickIcon() { 114 onClickIcon() {
120 this.timer && clearTimeout(this.timer); 115 this.timer && clearTimeout(this.timer);
121 this.timer = null; 116 this.timer = null;
122 this.set({ show: false }); 117 this.setData({ show: false });
123 }, 118 },
124 onClick(event) { 119 onClick(event) {
125 this.$emit('click', event); 120 this.$emit('click', event);
......
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
1 <view 3 <view
2 wx:if="{{ show }}" 4 wx:if="{{ show }}"
3 class="custom-class van-notice-bar {{ hasRightIcon ? 'van-notice-bar--within-icon' : '' }}" 5 class="custom-class {{ utils.bem('notice-bar', { withicon: mode, wrapable }) }}"
4 style="color: {{ color }}; background-color: {{ backgroundColor }};" 6 style="color: {{ color }}; background-color: {{ backgroundColor }};"
5 bind:tap="onClick" 7 bind:tap="onClick"
6 > 8 >
7 <view wx:if="{{ leftIcon }}" class="van-notice-bar__left-icon"> 9 <van-icon
8 <image src="{{ leftIcon }}" /> 10 wx:if="{{ leftIcon }}"
9 </view> 11 size="16px"
10 <view class="van-notice-bar__content-wrap"> 12 name="{{ leftIcon }}"
11 <view class="van-notice-bar__content {{ scrollable ? '' : 'van-ellipsis' }}" animation="{{ animationData }}"> 13 class="van-notice-bar__left-icon"
14 />
15 <slot wx:else name="left-icon" />
16
17 <view class="van-notice-bar__wrap">
18 <view class="van-notice-bar__content {{ !scrollable && !wrapable ? 'van-ellipsis' : '' }}" animation="{{ animationData }}">
12 {{ text }} 19 {{ text }}
13 </view> 20 </view>
14 </view> 21 </view>
...@@ -17,13 +24,14 @@ ...@@ -17,13 +24,14 @@
17 wx:if="{{ mode === 'closeable' }}" 24 wx:if="{{ mode === 'closeable' }}"
18 class="van-notice-bar__right-icon" 25 class="van-notice-bar__right-icon"
19 name="cross" 26 name="cross"
20 bind:tap="onClickIcon" 27 catch:tap="onClickIcon"
21 /> 28 />
22 <navigator 29 <navigator
23 wx:if="{{ mode === 'link' }}" 30 wx:elif="{{ mode === 'link' }}"
24 url="{{ url }}" 31 url="{{ url }}"
25 open-type="{{ openType }}" 32 open-type="{{ openType }}"
26 > 33 >
27 <van-icon class="van-notice-bar__right-icon" name="arrow" /> 34 <van-icon class="van-notice-bar__right-icon" name="arrow" />
28 </navigator> 35 </navigator>
36 <slot wx:else name="right-icon" />
29 </view> 37 </view>
......
1 @import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;height:40px;padding:0 15px;font-size:14px;line-height:24px;-webkit-align-items:center;align-items:center}.van-notice-bar--within-icon{position:relative;padding-right:40px}.van-notice-bar__left-icon{height:18px;min-width:20px;box-sizing:border-box}.van-notice-bar__left-icon>image{width:16px;height:16px}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px;font-size:16px}.van-notice-bar__content-wrap{position:relative;height:24px;overflow:hidden;-webkit-flex:1;flex:1}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:40px;height:var(--notice-bar-height,40px);padding:0 16px;padding:var(--notice-bar-padding,0 16px);font-size:14px;font-size:var(--notice-bar-font-size,14px);color:#ed6a0c;color:var(--notice-bar-text-color,#ed6a0c);line-height:24px;line-height:var(--notice-bar-line-height,24px);background-color:#fffbe8;background-color:var(--notice-bar-background-color,#fffbe8)}.van-notice-bar--withicon{position:relative;padding-right:40px}.van-notice-bar--wrapable{height:auto;padding:8px 16px;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:16px;font-size:var(--notice-bar-icon-size,16px);min-width:22px;min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px}.van-notice-bar__wrap{position:relative;-webkit-flex:1;flex:1;overflow:hidden;height:24px;height:var(--notice-bar-line-height,24px)}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { RED } from '../common/color'; 2 import { WHITE } from '../common/color';
3 import { safeArea } from '../mixins/safe-area';
4 VantComponent({ 3 VantComponent({
5 mixins: [safeArea()],
6 props: { 4 props: {
7 text: String, 5 message: String,
8 color: { 6 background: String,
7 type: {
9 type: String, 8 type: String,
10 value: '#fff' 9 value: 'danger'
11 }, 10 },
12 backgroundColor: { 11 color: {
13 type: String, 12 type: String,
14 value: RED 13 value: WHITE
15 }, 14 },
16 duration: { 15 duration: {
17 type: Number, 16 type: Number,
18 value: 3000 17 value: 3000
18 },
19 zIndex: {
20 type: Number,
21 value: 110
22 },
23 safeAreaInsetTop: {
24 type: Boolean,
25 value: false
19 } 26 }
20 }, 27 },
21 methods: { 28 methods: {
22 show() { 29 show() {
23 const { duration } = this.data; 30 const { duration, onOpened } = this.data;
24 clearTimeout(this.timer); 31 clearTimeout(this.timer);
25 this.set({ 32 this.setData({
26 show: true 33 show: true
27 }); 34 }, onOpened);
28 if (duration > 0 && duration !== Infinity) { 35 if (duration > 0 && duration !== Infinity) {
29 this.timer = setTimeout(() => { 36 this.timer = setTimeout(() => {
30 this.hide(); 37 this.hide();
...@@ -32,10 +39,17 @@ VantComponent({ ...@@ -32,10 +39,17 @@ VantComponent({
32 } 39 }
33 }, 40 },
34 hide() { 41 hide() {
42 const { onClose } = this.data;
35 clearTimeout(this.timer); 43 clearTimeout(this.timer);
36 this.set({ 44 this.setData({
37 show: false 45 show: false
38 }); 46 }, onClose);
47 },
48 onTap(event) {
49 const { onClick } = this.data;
50 if (onClick) {
51 onClick(event.detail);
52 }
39 } 53 }
40 } 54 }
41 }); 55 });
......
1 <van-transition 1 <van-transition
2 name="slide-down" 2 name="slide-down"
3 show="{{ show }}" 3 show="{{ show }}"
4 custom-class="van-notify" 4 custom-class="van-notify__container"
5 custom-style="background-color:{{ backgroundColor }}; color: {{ color }};" 5 custom-style="z-index: {{ zIndex }};"
6 bind:tap="onTap"
6 > 7 >
7 <view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-top" style="padding-top: {{ statusBarHeight }}px"></view> 8 <view
8 {{ text }} 9 class="van-notify van-notify--{{ type }}"
10 style="background:{{ background }};color:{{ color }};"
11 >
12 <view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-area"></view>
13 <text>{{ message }}</text>
14 </view>
9 </van-transition> 15 </van-transition>
......
1 @import '../common/index.wxss';.van-notify{position:fixed;top:0;z-index:110;width:100%;padding:6px 15px;font-size:14px;line-height:20px;text-align:center;word-break:break-all;box-sizing:border-box}.van-notify__safe-top{height:44px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-notify{text-align:center;word-wrap:break-word;padding:6px 15px;padding:var(--notify-padding,6px 15px);font-size:14px;font-size:var(--notify-font-size,14px);line-height:20px;line-height:var(--notify-line-height,20px)}.van-notify__container{position:fixed;top:0;box-sizing:border-box;width:100%}.van-notify__safe-area{height:constant(safe-area-inset-top);height:env(safe-area-inset-top)}.van-notify--primary{background-color:#1989fa;background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:#07c160;background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:#ee0a24;background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:#ff976a;background-color:var(--notify-warning-background-color,#ff976a)}
...\ No newline at end of file ...\ No newline at end of file
......
1 declare type NotifyOptions = { 1 interface NotifyOptions {
2 text: string; 2 type?: 'primary' | 'success' | 'danger' | 'warning';
3 color?: string; 3 color?: string;
4 backgroundColor?: string; 4 zIndex?: number;
5 message: string;
6 context?: any;
5 duration?: number; 7 duration?: number;
6 selector?: string; 8 selector?: string;
7 context?: any; 9 background?: string;
8 safeAreaInsetTop?: boolean; 10 safeAreaInsetTop?: boolean;
9 }; 11 onClick?: () => void;
12 onOpened?: () => void;
13 onClose?: () => void;
14 }
10 export default function Notify(options: NotifyOptions | string): void; 15 export default function Notify(options: NotifyOptions | string): void;
11 export {}; 16 export {};
......
1 import { isObj } from '../common/utils'; 1 import { WHITE } from '../common/color';
2 const defaultOptions = { 2 const defaultOptions = {
3 selector: '#van-notify', 3 selector: '#van-notify',
4 duration: 3000 4 type: 'danger',
5 message: '',
6 background: '',
7 duration: 3000,
8 zIndex: 110,
9 color: WHITE,
10 safeAreaInsetTop: false,
11 onClick: () => { },
12 onOpened: () => { },
13 onClose: () => { }
5 }; 14 };
6 function parseOptions(text) { 15 function parseOptions(message) {
7 return isObj(text) ? text : { text }; 16 return typeof message === 'string' ? { message } : message;
8 } 17 }
9 function getContext() { 18 function getContext() {
10 const pages = getCurrentPages(); 19 const pages = getCurrentPages();
...@@ -14,6 +23,7 @@ export default function Notify(options) { ...@@ -14,6 +23,7 @@ export default function Notify(options) {
14 options = Object.assign({}, defaultOptions, parseOptions(options)); 23 options = Object.assign({}, defaultOptions, parseOptions(options));
15 const context = options.context || getContext(); 24 const context = options.context || getContext();
16 const notify = context.selectComponent(options.selector); 25 const notify = context.selectComponent(options.selector);
26 delete options.context;
17 delete options.selector; 27 delete options.selector;
18 if (notify) { 28 if (notify) {
19 notify.set(options); 29 notify.set(options);
......
...@@ -2,10 +2,9 @@ import { VantComponent } from '../common/component'; ...@@ -2,10 +2,9 @@ import { VantComponent } from '../common/component';
2 VantComponent({ 2 VantComponent({
3 props: { 3 props: {
4 show: Boolean, 4 show: Boolean,
5 mask: Boolean,
6 customStyle: String, 5 customStyle: String,
7 duration: { 6 duration: {
8 type: [Number, Object], 7 type: null,
9 value: 300 8 value: 300
10 }, 9 },
11 zIndex: { 10 zIndex: {
......
1 <van-transition 1 <van-transition
2 show="{{ show }}" 2 show="{{ show }}"
3 custom-class="van-overlay" 3 custom-class="van-overlay"
4 custom-style="z-index: {{ zIndex }}; {{ mask ? 'background-color: rgba(0, 0, 0, .7);' : '' }}; {{ customStyle }}" 4 custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
5 duration="{{ duration }}" 5 duration="{{ duration }}"
6 bind:tap="onClick" 6 bind:tap="onClick"
7 catch:touchmove="noop" 7 catch:touchmove="noop"
......
1 @import '../common/index.wxss';.van-overlay{position:fixed;top:0;right:0;bottom:0;left:0}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.7);background-color:var(--overlay-background-color,rgba(0,0,0,.7))}
...\ No newline at end of file ...\ No newline at end of file
......
1 @import '../common/index.wxss';.van-panel{background:#fff}.van-panel__header-value{color:#f44}.van-panel__footer{padding:10px 15px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-panel{background:#fff;background:var(--panel-background-color,#fff)}.van-panel__header-value{color:#ee0a24;color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:8px 16px;padding:var(--panel-footer-padding,8px 16px)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -34,31 +34,17 @@ VantComponent({ ...@@ -34,31 +34,17 @@ VantComponent({
34 this.setIndex(defaultIndex); 34 this.setIndex(defaultIndex);
35 }); 35 });
36 }, 36 },
37 computed: {
38 count() {
39 return this.data.options.length;
40 },
41 baseOffset() {
42 const { data } = this;
43 return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
44 },
45 wrapperStyle() {
46 const { data } = this;
47 return [
48 `transition: ${data.duration}ms`,
49 `transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
50 `line-height: ${data.itemHeight}px`
51 ].join('; ');
52 }
53 },
54 watch: { 37 watch: {
55 defaultIndex(value) { 38 defaultIndex(value) {
56 this.setIndex(value); 39 this.setIndex(value);
57 } 40 }
58 }, 41 },
59 methods: { 42 methods: {
43 getCount() {
44 return this.data.options.length;
45 },
60 onTouchStart(event) { 46 onTouchStart(event) {
61 this.set({ 47 this.setData({
62 startY: event.touches[0].clientY, 48 startY: event.touches[0].clientY,
63 startOffset: this.data.offset, 49 startOffset: this.data.offset,
64 duration: 0 50 duration: 0
...@@ -67,17 +53,15 @@ VantComponent({ ...@@ -67,17 +53,15 @@ VantComponent({
67 onTouchMove(event) { 53 onTouchMove(event) {
68 const { data } = this; 54 const { data } = this;
69 const deltaY = event.touches[0].clientY - data.startY; 55 const deltaY = event.touches[0].clientY - data.startY;
70 this.set({ 56 this.setData({
71 offset: range(data.startOffset + deltaY, -(data.count * data.itemHeight), data.itemHeight) 57 offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight)
72 }); 58 });
73 }, 59 },
74 onTouchEnd() { 60 onTouchEnd() {
75 const { data } = this; 61 const { data } = this;
76 if (data.offset !== data.startOffset) { 62 if (data.offset !== data.startOffset) {
77 this.set({ 63 this.setData({ duration: DEFAULT_DURATION });
78 duration: DEFAULT_DURATION 64 const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
79 });
80 const index = range(Math.round(-data.offset / data.itemHeight), 0, data.count - 1);
81 this.setIndex(index, true); 65 this.setIndex(index, true);
82 } 66 }
83 }, 67 },
...@@ -87,8 +71,9 @@ VantComponent({ ...@@ -87,8 +71,9 @@ VantComponent({
87 }, 71 },
88 adjustIndex(index) { 72 adjustIndex(index) {
89 const { data } = this; 73 const { data } = this;
90 index = range(index, 0, data.count); 74 const count = this.getCount();
91 for (let i = index; i < data.count; i++) { 75 index = range(index, 0, count);
76 for (let i = index; i < count; i++) {
92 if (!this.isDisabled(data.options[i])) 77 if (!this.isDisabled(data.options[i]))
93 return i; 78 return i;
94 } 79 }
...@@ -115,9 +100,7 @@ VantComponent({ ...@@ -115,9 +100,7 @@ VantComponent({
115 userAction && this.$emit('change', index); 100 userAction && this.$emit('change', index);
116 }); 101 });
117 } 102 }
118 else { 103 return this.set({ offset });
119 return this.set({ offset });
120 }
121 }, 104 },
122 setValue(value) { 105 setValue(value) {
123 const { options } = this.data; 106 const { options } = this.data;
......
1 <wxs src="./index.wxs" module="getOptionText" />
2
1 <view 3 <view
2 class="van-picker-column custom-class" 4 class="van-picker-column custom-class"
3 style="height: {{ itemHeight * visibleItemCount }}px" 5 style="height: {{ itemHeight * visibleItemCount }}px"
...@@ -6,7 +8,7 @@ ...@@ -6,7 +8,7 @@
6 bind:touchend="onTouchEnd" 8 bind:touchend="onTouchEnd"
7 bind:touchcancel="onTouchEnd" 9 bind:touchcancel="onTouchEnd"
8 > 10 >
9 <view style="{{ wrapperStyle }}"> 11 <view style="transition: transform {{ duration }}ms; line-height: {{ itemHeight }}px; transform: translate3d(0, {{ offset + (itemHeight * (visibleItemCount - 1)) / 2 }}px, 0)">
10 <view 12 <view
11 wx:for="{{ options }}" 13 wx:for="{{ options }}"
12 wx:for-item="option" 14 wx:for-item="option"
...@@ -18,14 +20,3 @@ ...@@ -18,14 +20,3 @@
18 >{{ getOptionText(option, valueKey) }}</view> 20 >{{ getOptionText(option, valueKey) }}</view>
19 </view> 21 </view>
20 </view> 22 </view>
21
22 <wxs module="getOptionText">
23 function isObj(x) {
24 var type = typeof x;
25 return x !== null && (type === 'object' || type === 'function');
26 }
27
28 module.exports = function (option, valueKey) {
29 return isObj(option) && option[valueKey] ? option[valueKey] : option;
30 }
31 </wxs>
......
1 function isObj(x) {
2 var type = typeof x;
3 return x !== null && (type === 'object' || type === 'function');
4 }
5
6 module.exports = function (option, valueKey) {
7 return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
8 }
1 @import '../common/index.wxss';.van-picker-column{overflow:hidden;font-size:16px;text-align:center}.van-picker-column__item{padding:0 5px;color:#999}.van-picker-column__item--selected{font-weight:500;color:#333}.van-picker-column__item--disabled{opacity:.3}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-picker-column{overflow:hidden;text-align:center;color:#000;color:var(--picker-option-text-color,#000);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--picker-option-selected-text-color,#323233)}.van-picker-column__item--disabled{opacity:.3;opacity:var(--picker-option-disabled-opacity,.3)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 function isSimple(columns) { 2 import { pickerProps } from './shared';
3 return columns.length && !columns[0].values;
4 }
5 VantComponent({ 3 VantComponent({
6 classes: ['active-class', 'toolbar-class', 'column-class'], 4 classes: ['active-class', 'toolbar-class', 'column-class'],
7 props: { 5 props: Object.assign(Object.assign({}, pickerProps), { valueKey: {
8 title: String,
9 loading: Boolean,
10 showToolbar: Boolean,
11 confirmButtonText: String,
12 cancelButtonText: String,
13 visibleItemCount: {
14 type: Number,
15 value: 5
16 },
17 valueKey: {
18 type: String, 6 type: String,
19 value: 'text' 7 value: 'text'
20 }, 8 }, toolbarPosition: {
21 itemHeight: { 9 type: String,
10 value: 'top'
11 }, defaultIndex: {
22 type: Number, 12 type: Number,
23 value: 44 13 value: 0
24 }, 14 }, columns: {
25 columns: {
26 type: Array, 15 type: Array,
27 value: [], 16 value: [],
28 observer(columns = []) { 17 observer(columns = []) {
29 this.simple = isSimple(columns); 18 this.simple = columns.length && !columns[0].values;
30 this.children = this.selectAllComponents('.van-picker__column'); 19 this.children = this.selectAllComponents('.van-picker__column');
31 if (Array.isArray(this.children) && this.children.length) { 20 if (Array.isArray(this.children) && this.children.length) {
32 this.setColumns().catch(() => { }); 21 this.setColumns().catch(() => { });
33 } 22 }
34 } 23 }
35 } 24 } }),
36 },
37 beforeCreate() { 25 beforeCreate() {
38 this.children = []; 26 this.children = [];
39 }, 27 },
...@@ -89,7 +77,7 @@ VantComponent({ ...@@ -89,7 +77,7 @@ VantComponent({
89 setColumnValue(index, value) { 77 setColumnValue(index, value) {
90 const column = this.getColumn(index); 78 const column = this.getColumn(index);
91 if (column == null) { 79 if (column == null) {
92 return Promise.reject('setColumnValue: 对应列不存在'); 80 return Promise.reject(new Error('setColumnValue: 对应列不存在'));
93 } 81 }
94 return column.setValue(value); 82 return column.setValue(value);
95 }, 83 },
...@@ -101,7 +89,7 @@ VantComponent({ ...@@ -101,7 +89,7 @@ VantComponent({
101 setColumnIndex(columnIndex, optionIndex) { 89 setColumnIndex(columnIndex, optionIndex) {
102 const column = this.getColumn(columnIndex); 90 const column = this.getColumn(columnIndex);
103 if (column == null) { 91 if (column == null) {
104 return Promise.reject('setColumnIndex: 对应列不存在'); 92 return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
105 } 93 }
106 return column.setIndex(optionIndex); 94 return column.setIndex(optionIndex);
107 }, 95 },
...@@ -113,7 +101,7 @@ VantComponent({ ...@@ -113,7 +101,7 @@ VantComponent({
113 setColumnValues(index, options, needReset = true) { 101 setColumnValues(index, options, needReset = true) {
114 const column = this.children[index]; 102 const column = this.children[index];
115 if (column == null) { 103 if (column == null) {
116 return Promise.reject('setColumnValues: 对应列不存在'); 104 return Promise.reject(new Error('setColumnValues: 对应列不存在'));
117 } 105 }
118 const isSame = JSON.stringify(column.data.options) === JSON.stringify(options); 106 const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
119 if (isSame) { 107 if (isSame) {
......
1 <view class="van-picker custom-class"> 1 <template name="toolbar">
2 <view 2 <view
3 wx:if="{{ showToolbar }}" 3 wx:if="{{ showToolbar }}"
4 class="van-picker__toolbar van-hairline--top-bottom toolbar-class" 4 class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
10 data-type="cancel" 10 data-type="cancel"
11 bindtap="emit" 11 bindtap="emit"
12 > 12 >
13 {{ cancelButtonText || '取消' }} 13 {{ cancelButtonText }}
14 </view> 14 </view>
15 <view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view> 15 <view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
16 <view 16 <view
...@@ -20,9 +20,13 @@ ...@@ -20,9 +20,13 @@
20 data-type="confirm" 20 data-type="confirm"
21 bindtap="emit" 21 bindtap="emit"
22 > 22 >
23 {{ confirmButtonText || '确认' }} 23 {{ confirmButtonText }}
24 </view> 24 </view>
25 </view> 25 </view>
26 </template>
27
28 <view class="van-picker custom-class">
29 <template is="toolbar" wx:if="{{ toolbarPosition === 'top' }}" data="{{ showToolbar, cancelButtonText, title, confirmButtonText }}"></template>
26 <view wx:if="{{ loading }}" class="van-picker__loading"> 30 <view wx:if="{{ loading }}" class="van-picker__loading">
27 <loading color="#1989fa"/> 31 <loading color="#1989fa"/>
28 </view> 32 </view>
...@@ -39,7 +43,7 @@ ...@@ -39,7 +43,7 @@
39 custom-class="column-class" 43 custom-class="column-class"
40 value-key="{{ valueKey }}" 44 value-key="{{ valueKey }}"
41 initial-options="{{ isSimple(columns) ? item : item.values }}" 45 initial-options="{{ isSimple(columns) ? item : item.values }}"
42 default-index="{{ item.defaultIndex }}" 46 default-index="{{ item.defaultIndex || defaultIndex }}"
43 item-height="{{ itemHeight }}" 47 item-height="{{ itemHeight }}"
44 visible-item-count="{{ visibleItemCount }}" 48 visible-item-count="{{ visibleItemCount }}"
45 active-class="active-class" 49 active-class="active-class"
...@@ -50,6 +54,7 @@ ...@@ -50,6 +54,7 @@
50 style="height: {{ itemHeight }}px" 54 style="height: {{ itemHeight }}px"
51 /> 55 />
52 </view> 56 </view>
57 <template is="toolbar" wx:if="{{ toolbarPosition === 'bottom' }}" data="{{ showToolbar, cancelButtonText, title, confirmButtonText }}"></template>
53 </view> 58 </view>
54 59
55 <wxs module="isSimple"> 60 <wxs module="isSimple">
......
1 @import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;background-color:#fff;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:-webkit-flex;display:flex;height:44px;line-height:44px;-webkit-justify-content:space-between;justify-content:space-between}.van-picker__cancel,.van-picker__confirm{padding:0 15px;font-size:14px;color:#1989fa}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5}.van-picker__title{max-width:50%;font-size:16px;font-weight:500;text-align:center}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;background-color:hsla(0,0%,100%,.9);-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;pointer-events:none;-webkit-transform:translateY(-50%);transform:translateY(-50%)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;-webkit-user-select:none;user-select:none;background-color:#fff;background-color:var(--picker-background-color,#fff)}.van-picker__toolbar{display:-webkit-flex;display:flex;-webkit-justify-content:space-between;justify-content:space-between;height:44px;height:var(--picker-toolbar-height,44px);line-height:44px;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#1989fa;color:var(--picker-action-text-color,#1989fa)}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5;background-color:var(--picker-action-active-color,#f2f3f5)}.van-picker__title{max-width:50%;text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;background-color:hsla(0,0%,100%,.9);background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9))}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);pointer-events:none}
...\ No newline at end of file ...\ No newline at end of file
......
1 export declare const pickerProps: {
2 title: StringConstructor;
3 loading: BooleanConstructor;
4 showToolbar: BooleanConstructor;
5 cancelButtonText: {
6 type: StringConstructor;
7 value: string;
8 };
9 confirmButtonText: {
10 type: StringConstructor;
11 value: string;
12 };
13 visibleItemCount: {
14 type: NumberConstructor;
15 value: number;
16 };
17 itemHeight: {
18 type: NumberConstructor;
19 value: number;
20 };
21 };
1 export const pickerProps = {
2 title: String,
3 loading: Boolean,
4 showToolbar: Boolean,
5 cancelButtonText: {
6 type: String,
7 value: '取消'
8 },
9 confirmButtonText: {
10 type: String,
11 value: '确认'
12 },
13 visibleItemCount: {
14 type: Number,
15 value: 5
16 },
17 itemHeight: {
18 type: Number,
19 value: 44
20 }
21 };
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { transition } from '../mixins/transition'; 2 import { transition } from '../mixins/transition';
3 import { safeArea } from '../mixins/safe-area';
4 VantComponent({ 3 VantComponent({
5 classes: [ 4 classes: [
6 'enter-class', 5 'enter-class',
...@@ -10,14 +9,16 @@ VantComponent({ ...@@ -10,14 +9,16 @@ VantComponent({
10 'leave-active-class', 9 'leave-active-class',
11 'leave-to-class' 10 'leave-to-class'
12 ], 11 ],
13 mixins: [transition(false), safeArea()], 12 mixins: [transition(false)],
14 props: { 13 props: {
14 round: Boolean,
15 closeable: Boolean,
16 customStyle: String,
17 overlayStyle: String,
15 transition: { 18 transition: {
16 type: String, 19 type: String,
17 observer: 'observeClass' 20 observer: 'observeClass'
18 }, 21 },
19 customStyle: String,
20 overlayStyle: String,
21 zIndex: { 22 zIndex: {
22 type: Number, 23 type: Number,
23 value: 100 24 value: 100
...@@ -26,6 +27,14 @@ VantComponent({ ...@@ -26,6 +27,14 @@ VantComponent({
26 type: Boolean, 27 type: Boolean,
27 value: true 28 value: true
28 }, 29 },
30 closeIcon: {
31 type: String,
32 value: 'cross'
33 },
34 closeIconPosition: {
35 type: String,
36 value: 'top-right'
37 },
29 closeOnClickOverlay: { 38 closeOnClickOverlay: {
30 type: Boolean, 39 type: Boolean,
31 value: true 40 value: true
...@@ -34,12 +43,23 @@ VantComponent({ ...@@ -34,12 +43,23 @@ VantComponent({
34 type: String, 43 type: String,
35 value: 'center', 44 value: 'center',
36 observer: 'observeClass' 45 observer: 'observeClass'
46 },
47 safeAreaInsetBottom: {
48 type: Boolean,
49 value: true
50 },
51 safeAreaInsetTop: {
52 type: Boolean,
53 value: false
37 } 54 }
38 }, 55 },
39 created() { 56 created() {
40 this.observeClass(); 57 this.observeClass();
41 }, 58 },
42 methods: { 59 methods: {
60 onClickCloseIcon() {
61 this.$emit('close');
62 },
43 onClickOverlay() { 63 onClickOverlay() {
44 this.$emit('click-overlay'); 64 this.$emit('click-overlay');
45 if (this.data.closeOnClickOverlay) { 65 if (this.data.closeOnClickOverlay) {
...@@ -48,10 +68,13 @@ VantComponent({ ...@@ -48,10 +68,13 @@ VantComponent({
48 }, 68 },
49 observeClass() { 69 observeClass() {
50 const { transition, position } = this.data; 70 const { transition, position } = this.data;
51 this.updateClasses(transition || position); 71 const updateData = {
72 name: transition || position
73 };
52 if (transition === 'none') { 74 if (transition === 'none') {
53 this.set({ duration: 0 }); 75 updateData.duration = 0;
54 } 76 }
77 this.setData(updateData);
55 } 78 }
56 } 79 }
57 }); 80 });
......
1 { 1 {
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-icon": "../icon/index",
4 "van-overlay": "../overlay/index" 5 "van-overlay": "../overlay/index"
5 } 6 }
6 } 7 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <van-overlay 3 <van-overlay
4 wx:if="{{ inited && overlay }}" 4 wx:if="{{ overlay }}"
5 mask
6 show="{{ show }}" 5 show="{{ show }}"
7 z-index="{{ zIndex }}" 6 z-index="{{ zIndex }}"
8 custom-style="{{ overlayStyle }}" 7 custom-style="{{ overlayStyle }}"
...@@ -11,10 +10,15 @@ ...@@ -11,10 +10,15 @@
11 /> 10 />
12 <view 11 <view
13 wx:if="{{ inited }}" 12 wx:if="{{ inited }}"
14 class="custom-class {{ classes }} {{ utils.bem('popup', [position, { safe: isIPhoneX && safeAreaInsetBottom }]) }}" 13 class="custom-class {{ classes }} {{ utils.bem('popup', [position, { round, safe: safeAreaInsetBottom, safeTop: safeAreaInsetTop }]) }}"
15 style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}" 14 style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }};{{ customStyle }}"
16 bind:transitionend="onTransitionEnd" 15 bind:transitionend="onTransitionEnd"
17 > 16 >
18 <view wx:if="{{ safeAreaInsetTop }}" class="van-popup__safe-top" style="padding-top: {{ statusBarHeight }}px;"></view>
19 <slot /> 17 <slot />
18 <van-icon
19 wx:if="{{ closeable }}"
20 name="{{ closeIcon }}"
21 class="van-popup__close-icon van-popup__close-icon--{{ closeIconPosition }}"
22 bind:tap="onClickCloseIcon"
23 />
20 </view> 24 </view>
......
1 @import '../common/index.wxss';.van-popup{position:fixed;top:50%;left:50%;max-height:100%;overflow-y:auto;background-color:#fff;box-sizing:border-box;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;transition-timing-function:ease}.van-popup--center{-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--top{top:0;right:auto;bottom:auto;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--right{top:50%;right:0;bottom:auto;left:auto;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom{top:auto;right:auto;bottom:0;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--left{top:50%;right:auto;bottom:auto;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom.van-popup--safe{padding-bottom:34px}.van-popup--left .van-popup__safe-top,.van-popup--right .van-popup__safe-top,.van-popup--top .van-popup__safe-top{height:44px}.van-popup--bottom .van-popup__safe-top,.van-popup--center .van-popup__safe-top{padding-top:0!important}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(-50%,100%,0);transform:translate3d(-50%,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(-50%,-100%,0);transform:translate3d(-50%,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-popup{position:fixed;box-sizing:border-box;max-height:100%;overflow-y:auto;transition-timing-function:ease;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;background-color:#fff;background-color:var(--popup-background-color,#fff)}.van-popup--center{top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:20px;border-radius:var(--popup-round-border-radius,20px)}.van-popup--top{top:0;left:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 20px 20px;border-radius:0 0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px)}.van-popup--right{top:50%;right:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:20px 0 0 20px;border-radius:var(--popup-round-border-radius,20px) 0 0 var(--popup-round-border-radius,20px)}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:20px 20px 0 0;border-radius:var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0 0}.van-popup--left{top:50%;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 20px 20px 0;border-radius:0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0}.van-popup--bottom.van-popup--safe{padding-bottom:env(safe-area-inset-bottom)}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{position:absolute;z-index:1;z-index:var(--popup-close-icon-z-index,1);color:#969799;color:var(--popup-close-icon-color,#969799);font-size:18px;font-size:var(--popup-close-icon-size,18px)}.van-popup__close-icon--top-left{top:16px;top:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{top:16px;top:var(--popup-close-icon-margin,16px);right:16px;right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:16px;bottom:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{right:16px;right:var(--popup-close-icon-margin,16px);bottom:16px;bottom:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { BLUE } from '../common/color'; 2 import { BLUE } from '../common/color';
3 import { addUnit } from '../common/utils';
3 VantComponent({ 4 VantComponent({
4 props: { 5 props: {
5 inactive: Boolean, 6 inactive: Boolean,
6 percentage: Number, 7 percentage: Number,
7 pivotText: String, 8 pivotText: String,
8 pivotColor: String, 9 pivotColor: String,
10 trackColor: String,
9 showPivot: { 11 showPivot: {
10 type: Boolean, 12 type: Boolean,
11 value: true 13 value: true
...@@ -17,48 +19,19 @@ VantComponent({ ...@@ -17,48 +19,19 @@ VantComponent({
17 textColor: { 19 textColor: {
18 type: String, 20 type: String,
19 value: '#fff' 21 value: '#fff'
20 }
21 },
22 data: {
23 pivotWidth: 0,
24 progressWidth: 0
25 },
26 watch: {
27 pivotText: 'getWidth',
28 showPivot: 'getWidth'
29 },
30 computed: {
31 portionStyle() {
32 const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
33 const background = this.getCurrentColor();
34 return `width: ${width}; background: ${background}; `;
35 }, 22 },
36 pivotStyle() { 23 strokeWidth: {
37 const color = this.data.textColor; 24 type: null,
38 const background = this.data.pivotColor || this.getCurrentColor(); 25 observer: 'setStrokeWidthUnit'
39 return `color: ${color}; background: ${background}`;
40 },
41 text() {
42 return this.data.pivotText || this.data.percentage + '%';
43 } 26 }
44 }, 27 },
45 mounted() { 28 data: {
46 this.getWidth(); 29 strokeWidthUnit: '4px'
47 }, 30 },
48 methods: { 31 methods: {
49 getCurrentColor() { 32 setStrokeWidthUnit(val) {
50 return this.data.inactive ? '#cacaca' : this.data.color; 33 this.setData({
51 }, 34 strokeWidthUnit: addUnit(val)
52 getWidth() {
53 this.getRect('.van-progress').then(rect => {
54 this.set({
55 progressWidth: rect.width
56 });
57 });
58 this.getRect('.van-progress__pivot').then(rect => {
59 this.set({
60 pivotWidth: rect.width || 0
61 });
62 }); 35 });
63 } 36 }
64 } 37 }
......
1 <view class="van-progress custom-class"> 1 <wxs src="./index.wxs" module="getters" />
2
3 <view
4 class="van-progress custom-class"
5 style="height: {{ strokeWidthUnit }}; {{ trackColor ? 'background: ' + trackColor : '' }}"
6 >
2 <view 7 <view
3 class="van-progress__portion {{ showPivot && text ? 'van-progress__portion--with-pivot' : '' }}" 8 class="van-progress__portion"
4 style="{{ portionStyle }}" 9 style="width: {{ percentage }}%; background: {{ inactive ? '#cacaca' : color }}"
5 > 10 >
6 <view 11 <view
7 wx:if="{{ showPivot && text }}" 12 wx:if="{{ showPivot && getters.text(pivotText, percentage) }}"
8 style="{{ pivotStyle }}" 13 style="color: {{ textColor }}; background: {{ pivotColor ? pivotColor : inactive ? '#cacaca' : color }}"
9 class="van-progress__pivot" 14 class="van-progress__pivot"
10 > 15 >
11 {{ text }} 16 {{ getters.text(pivotText, percentage) }}
12 </view> 17 </view>
13 </view> 18 </view>
14 </view> 19 </view>
......
1 module.exports = {
2 text: function(pivotText, percentage) {
3 return pivotText || percentage + '%';
4 }
5 };
1 @import '../common/index.wxss';.van-progress{height:4px;position:relative;border-radius:4px;background:#e5e5e5}.van-progress__portion{left:0;height:100%;position:absolute;border-radius:inherit}.van-progress__portion--with-pivot{border-top-right-radius:0;border-bottom-right-radius:0}.van-progress__pivot{top:50%;right:0;min-width:2em;padding:0 5px;font-size:10px;position:absolute;line-height:1.6;text-align:center;border-radius:1em;word-break:keep-all;box-sizing:border-box;background-color:#e5e5e5;-webkit-transform:translate(100%,-50%);transform:translate(100%,-50%)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-progress{position:relative;height:4px;height:var(--progress-height,4px);border-radius:4px;border-radius:var(--progress-height,4px);background:#e5e5e5;background:var(--progress-background-color,#e5e5e5)}.van-progress__portion{position:absolute;left:0;height:100%;border-radius:inherit;background:#1989fa;background:var(--progress-color,#1989fa)}.van-progress__pivot{position:absolute;top:50%;right:0;box-sizing:border-box;min-width:2em;text-align:center;word-break:keep-all;border-radius:1em;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#fff;color:var(--progress-pivot-text-color,#fff);padding:0 5px;padding:var(--progress-pivot-padding,0 5px);font-size:10px;font-size:var(--progress-pivot-font-size,10px);line-height:1.6;line-height:var(--progress-pivot-line-height,1.6);background-color:#1989fa;background-color:var(--progress-pivot-background-color,#1989fa)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -5,28 +5,33 @@ VantComponent({ ...@@ -5,28 +5,33 @@ VantComponent({
5 name: 'radio', 5 name: 'radio',
6 type: 'descendant', 6 type: 'descendant',
7 linked(target) { 7 linked(target) {
8 const { value, disabled } = this.data; 8 this.children = this.children || [];
9 target.set({ 9 this.children.push(target);
10 value: value, 10 this.updateChild(target);
11 disabled: disabled || target.data.disabled 11 },
12 }); 12 unlinked(target) {
13 this.children = this.children.filter((child) => child !== target);
13 } 14 }
14 }, 15 },
15 props: { 16 props: {
16 value: null, 17 value: {
17 disabled: Boolean 18 type: null,
19 observer: 'updateChildren'
20 },
21 disabled: {
22 type: Boolean,
23 observer: 'updateChildren'
24 }
18 }, 25 },
19 watch: { 26 methods: {
20 value(value) { 27 updateChildren() {
21 const children = this.getRelationNodes('../radio/index'); 28 (this.children || []).forEach((child) => this.updateChild(child));
22 children.forEach(child => {
23 child.set({ value });
24 });
25 }, 29 },
26 disabled(disabled) { 30 updateChild(child) {
27 const children = this.getRelationNodes('../radio/index'); 31 const { value, disabled } = this.data;
28 children.forEach(child => { 32 child.setData({
29 child.set({ disabled: disabled || child.data.disabled }); 33 value,
34 disabled: disabled || child.data.disabled
30 }); 35 });
31 } 36 }
32 } 37 }
......
1 { 1 {
2 "component": true, 2 "component": true
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 } 3 }
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { addUnit } from '../common/utils';
2 VantComponent({ 3 VantComponent({
3 field: true, 4 field: true,
4 relation: { 5 relation: {
5 name: 'radio-group', 6 name: 'radio-group',
6 type: 'ancestor' 7 type: 'ancestor',
8 linked(target) {
9 this.parent = target;
10 },
11 unlinked() {
12 this.parent = null;
13 }
7 }, 14 },
8 classes: ['icon-class', 'label-class'], 15 classes: ['icon-class', 'label-class'],
9 props: { 16 props: {
10 name: null,
11 value: null, 17 value: null,
12 disabled: Boolean, 18 disabled: Boolean,
19 useIconSlot: Boolean,
20 checkedColor: String,
21 labelPosition: {
22 type: String,
23 value: 'right'
24 },
13 labelDisabled: Boolean, 25 labelDisabled: Boolean,
14 labelPosition: String, 26 shape: {
15 checkedColor: String 27 type: String,
28 value: 'round'
29 },
30 iconSize: {
31 type: null,
32 observer: 'setIconSizeUnit'
33 }
34 },
35 data: {
36 iconSizeWithUnit: '20px'
16 }, 37 },
17 methods: { 38 methods: {
39 setIconSizeUnit(val) {
40 this.setData({
41 iconSizeWithUnit: addUnit(val)
42 });
43 },
18 emitChange(value) { 44 emitChange(value) {
19 const instance = this.getRelationNodes('../radio-group/index')[0] || this; 45 const instance = this.parent || this;
20 instance.$emit('input', value); 46 instance.$emit('input', value);
21 instance.$emit('change', value); 47 instance.$emit('change', value);
22 }, 48 },
23 onChange(event) { 49 onChange(event) {
24 this.emitChange(event.detail.value); 50 console.log(event);
51 this.emitChange(this.data.name);
25 }, 52 },
26 onClickLabel() { 53 onClickLabel() {
27 if (!this.data.disabled && !this.data.labelDisabled) { 54 const { disabled, labelDisabled, name } = this.data;
28 this.emitChange(this.data.name); 55 if (!disabled && !labelDisabled) {
56 this.emitChange(name);
29 } 57 }
30 } 58 }
31 } 59 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <view class="van-radio custom-class"> 3 <view class="van-radio custom-class">
4 <view class="van-radio__input"> 4 <view
5 <radio-group bindchange="onChange"> 5 wx:if="{{ labelPosition === 'left' }}"
6 <radio 6 class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled }]) }}"
7 value="{{ name }}" 7 bindtap="onClickLabel"
8 checked="{{ value === name }}" 8 >
9 disabled="{{ disabled }}" 9 <slot />
10 class="van-radio__control" 10 </view>
11 /> 11 <view class="van-radio__icon-wrap" style="font-size: {{ iconSizeWithUnit }};" bindtap="onChange">
12 </radio-group> 12 <slot wx:if="{{ useIconSlot }}" name="icon" />
13 <van-icon 13 <van-icon
14 class="{{ utils.bem('radio__icon', { disabled, checked: !disabled && name === value, check: !disabled && name !== value }) }}" 14 wx:else
15 name="success"
16 class="{{ utils.bem('radio__icon', [shape, { disabled, checked: value === name }]) }}"
17 style="{{ checkedColor && !disabled && value === name ? 'border-color:' + checkedColor + '; background-color:' + checkedColor + ';' : '' }}"
15 custom-class="icon-class" 18 custom-class="icon-class"
16 color="{{ value === name ? checkedColor : '' }}" 19 custom-style="line-height: {{ iconSizeWithUnit }};font-size: .8em;display: block;"
17 name="{{ value === name ? 'checked' : 'circle' }}"
18 /> 20 />
19 </view> 21 </view>
20 <view class="van-radio__label van-radio__label--{{ labelPosition }} label-class" bindtap="onClickLabel"> 22 <view
23 wx:if="{{ labelPosition === 'right' }}"
24 class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled }]) }}"
25 bindtap="onClickLabel"
26 >
21 <slot /> 27 <slot />
22 </view> 28 </view>
23 </view> 29 </view>
......
1 @import '../common/index.wxss';.van-radio{overflow:hidden;line-height:1;-webkit-user-select:none;user-select:none}.van-radio__input,.van-radio__label{display:inline-block;vertical-align:middle}.van-radio__input{position:relative;font-size:20px}.van-radio__control{z-index:1;position:absolute;top:0;left:0;width:100%;height:100%;margin:0;opacity:0}.van-radio__label{margin-left:10px;color:#333;font-size:16px;line-height:20px}.van-radio__label--left{margin:0 10px 0 0;float:left}.van-radio__label:empty{margin:0}.van-radio__icon{pointer-events:none;display:block;line-height:0}.van-radio__icon--disabled{color:#e5e5e5}.van-radio__icon--checked{color:#1989fa}.van-radio__icon--check{color:#c9c9c9}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-radio{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{-webkit-flex:none;flex:none}.van-radio__icon{display:block;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;border:1px solid #e5e5e5;border:1px solid var(--radio-border-color,#e5e5e5);font-size:20px;font-size:var(--radio-size,20px);transition-duration:.2s;transition-duration:var(--radio-transition-duration,.2s)}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--radio-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--radio-checked-icon-color,#1989fa)}.van-radio__icon--disabled{background-color:#ebedf0;background-color:var(--radio-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:#c8c9cc;color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;margin-left:10px;margin-left:var(--radio-label-margin,10px);color:#323233;color:var(--radio-label-color,#323233);line-height:20px;line-height:var(--radio-size,20px)}.van-radio__label--left{float:left;margin:0 10px 0 0;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:#c8c9cc;color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { addUnit } from '../common/utils';
2 VantComponent({ 3 VantComponent({
3 field: true, 4 field: true,
4 classes: ['icon-class'], 5 classes: ['icon-class'],
5 props: { 6 props: {
7 value: Number,
6 readonly: Boolean, 8 readonly: Boolean,
7 disabled: Boolean, 9 disabled: Boolean,
8 size: { 10 allowHalf: Boolean,
9 type: Number, 11 size: null,
10 value: 20
11 },
12 icon: { 12 icon: {
13 type: String, 13 type: String,
14 value: 'star' 14 value: 'star'
...@@ -33,46 +33,52 @@ VantComponent({ ...@@ -33,46 +33,52 @@ VantComponent({
33 type: Number, 33 type: Number,
34 value: 5 34 value: 5
35 }, 35 },
36 value: { 36 gutter: {
37 type: Number, 37 type: null,
38 value: 0 38 observer: 'setGutterWithUnit'
39 },
40 touchable: {
41 type: Boolean,
42 value: true
39 } 43 }
40 }, 44 },
41 data: { 45 data: {
42 innerValue: 0 46 innerValue: 0,
47 gutterWithUnit: undefined
43 }, 48 },
44 watch: { 49 watch: {
45 value(value) { 50 value(value) {
46 if (value !== this.data.innerValue) { 51 if (value !== this.data.innerValue) {
47 this.set({ innerValue: value }); 52 this.setData({ innerValue: value });
48 } 53 }
49 } 54 }
50 }, 55 },
51 computed: {
52 list() {
53 const { count, innerValue } = this.data;
54 return Array.from({ length: count }, (_, index) => index < innerValue);
55 }
56 },
57 methods: { 56 methods: {
57 setGutterWithUnit(val) {
58 this.setData({
59 gutterWithUnit: addUnit(val)
60 });
61 },
58 onSelect(event) { 62 onSelect(event) {
59 const { data } = this; 63 const { data } = this;
60 const { index } = event.currentTarget.dataset; 64 const { score } = event.currentTarget.dataset;
61 if (!data.disabled && !data.readonly) { 65 if (!data.disabled && !data.readonly) {
62 this.set({ innerValue: index + 1 }); 66 this.setData({ innerValue: score + 1 });
63 this.$emit('input', index + 1); 67 this.$emit('input', score + 1);
64 this.$emit('change', index + 1); 68 this.$emit('change', score + 1);
65 } 69 }
66 }, 70 },
67 onTouchMove(event) { 71 onTouchMove(event) {
68 const { clientX, clientY } = event.touches[0]; 72 const { touchable } = this.data;
69 this.getRect('.van-rate__item', true).then(list => { 73 if (!touchable)
70 const target = list.find(item => clientX >= item.left && 74 return;
71 clientX <= item.right && 75 const { clientX } = event.touches[0];
72 clientY >= item.top && 76 this.getRect('.van-rate__icon', true).then((list) => {
73 clientY <= item.bottom); 77 const target = list
78 .sort(item => item.right - item.left)
79 .find(item => clientX >= item.left && clientX <= item.right);
74 if (target != null) { 80 if (target != null) {
75 this.onSelect(Object.assign({}, event, { currentTarget: target })); 81 this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target }));
76 } 82 }
77 }); 83 });
78 } 84 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
1 <view 3 <view
2 class="van-rate custom-class" 4 class="van-rate custom-class"
3 bind:touchmove="onTouchMove" 5 bind:touchmove="onTouchMove"
4 > 6 >
5 <van-icon 7 <view
6 wx:for="{{ list }}"
7 wx:key="index"
8 class="van-rate__item" 8 class="van-rate__item"
9 custom-class="icon-class" 9 wx:for="{{ count }}"
10 size="{{ size }}px" 10 wx:key="index"
11 data-index="{{ index }}" 11 style="padding-right: {{ index !== count - 1 ? gutterWithUnit : '' }}"
12 name="{{ item ? icon : voidIcon }}" 12 >
13 color="{{ disabled ? disabledColor : item ? color : voidColor }}" 13 <van-icon
14 bind:click="onSelect" 14 name="{{ index + 1 <= innerValue ? icon : voidIcon }}"
15 /> 15 size="{{ size }}"
16 class="van-rate__icon"
17 custom-class="icon-class"
18 data-score="{{ index }}"
19 color="{{ disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor }}"
20 bind:click="onSelect"
21 />
22
23 <van-icon
24 wx:if="{{ allowHalf }}"
25 size="{{ size }}"
26 name="{{ index + 0.5 <= innerValue ? icon : voidIcon }}"
27 class="{{ utils.bem('rate__icon', ['half']) }}"
28 custom-class="icon-class"
29 data-score="{{ index - 0.5 }}"
30 color="{{ disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor }}"
31 bind:click="onSelect"
32 />
33 </view>
16 </view> 34 </view>
......
1 @import '../common/index.wxss';.van-rate{-webkit-user-select:none;user-select:none}.van-rate__item{width:1em;padding:0 2px;box-sizing:initial}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-rate{display:-webkit-inline-flex;display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{position:relative;padding:0 2px;padding:0 var(--rate-horizontal-padding,2px)}.van-rate__icon{display:block;height:1em;font-size:20px;font-size:var(--rate-icon-size,20px)}.van-rate__icon--half{position:absolute;top:0;width:.5em;overflow:hidden;left:2px;left:var(--rate-horizontal-padding,2px)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -27,7 +27,7 @@ VantComponent({ ...@@ -27,7 +27,7 @@ VantComponent({
27 const style = gutter 27 const style = gutter
28 ? `margin-right: ${margin}; margin-left: ${margin};` 28 ? `margin-right: ${margin}; margin-left: ${margin};`
29 : ''; 29 : '';
30 this.set({ style }); 30 this.setData({ style });
31 this.getRelationNodes('../col/index').forEach(col => { 31 this.getRelationNodes('../col/index').forEach(col => {
32 col.setGutter(this.data.gutter); 32 col.setGutter(this.data.gutter);
33 }); 33 });
......
1 @import '../common/index.wxss';.van-row:after{content:"";display:table;clear:both}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-row:after{display:table;clear:both;content:""}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -3,6 +3,7 @@ VantComponent({ ...@@ -3,6 +3,7 @@ VantComponent({
3 field: true, 3 field: true,
4 classes: ['field-class', 'input-class', 'cancel-class'], 4 classes: ['field-class', 'input-class', 'cancel-class'],
5 props: { 5 props: {
6 label: String,
6 focus: Boolean, 7 focus: Boolean,
7 error: Boolean, 8 error: Boolean,
8 disabled: Boolean, 9 disabled: Boolean,
...@@ -10,8 +11,19 @@ VantComponent({ ...@@ -10,8 +11,19 @@ VantComponent({
10 inputAlign: String, 11 inputAlign: String,
11 showAction: Boolean, 12 showAction: Boolean,
12 useActionSlot: Boolean, 13 useActionSlot: Boolean,
14 useLeftIconSlot: Boolean,
15 useRightIconSlot: Boolean,
16 leftIcon: {
17 type: String,
18 value: 'search'
19 },
20 rightIcon: String,
13 placeholder: String, 21 placeholder: String,
14 placeholderStyle: String, 22 placeholderStyle: String,
23 actionText: {
24 type: String,
25 value: '取消'
26 },
15 background: { 27 background: {
16 type: String, 28 type: String,
17 value: '#ffffff' 29 value: '#ffffff'
...@@ -24,17 +36,26 @@ VantComponent({ ...@@ -24,17 +36,26 @@ VantComponent({
24 type: String, 36 type: String,
25 value: 'square' 37 value: 'square'
26 }, 38 },
27 label: String 39 clearable: {
40 type: Boolean,
41 value: true
42 }
28 }, 43 },
29 methods: { 44 methods: {
30 onChange(event) { 45 onChange(event) {
31 this.set({ value: event.detail }); 46 this.setData({ value: event.detail });
32 this.$emit('change', event.detail); 47 this.$emit('change', event.detail);
33 }, 48 },
34 onCancel() { 49 onCancel() {
35 this.set({ value: '' }); 50 /**
36 this.$emit('cancel'); 51 * 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
37 this.$emit('change', ''); 52 * https://github.com/youzan/vant-weapp/issues/1768
53 */
54 setTimeout(() => {
55 this.setData({ value: '' });
56 this.$emit('cancel');
57 this.$emit('change', '');
58 }, 200);
38 }, 59 },
39 onSearch() { 60 onSearch() {
40 this.$emit('search', this.data.value); 61 this.$emit('search', this.data.value);
......
1 { 1 {
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-field": "../field/index" 4 "van-field": "../field/index"
6 } 5 }
7 } 6 }
......
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
9 <slot wx:else name="label" /> 9 <slot wx:else name="label" />
10 10
11 <van-field 11 <van-field
12 clearable
13 type="search" 12 type="search"
14 left-icon="search" 13 left-icon="{{ !useLeftIconSlot ? leftIcon : '' }}"
14 right-icon="{{ !useRightIconSlot ? rightIcon : '' }}"
15 focus="{{ focus }}" 15 focus="{{ focus }}"
16 error="{{ error }}" 16 error="{{ error }}"
17 border="{{ false }}" 17 border="{{ false }}"
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
20 value="{{ value }}" 20 value="{{ value }}"
21 disabled="{{ disabled }}" 21 disabled="{{ disabled }}"
22 readonly="{{ readonly }}" 22 readonly="{{ readonly }}"
23 clearable="{{ clearable }}"
23 maxlength="{{ maxlength }}" 24 maxlength="{{ maxlength }}"
24 input-align="{{ inputAlign }}" 25 input-align="{{ inputAlign }}"
25 input-class="input-class" 26 input-class="input-class"
...@@ -31,7 +32,10 @@ ...@@ -31,7 +32,10 @@
31 bind:change="onChange" 32 bind:change="onChange"
32 bind:confirm="onSearch" 33 bind:confirm="onSearch"
33 bind:clear="onClear" 34 bind:clear="onClear"
34 /> 35 >
36 <slot wx:if="{{ useLeftIconSlot }}" name="left-icon" slot="left-icon" />
37 <slot wx:if="{{ useRightIconSlot }}" name="right-icon" slot="right-icon" />
38 </van-field>
35 </view> 39 </view>
36 40
37 <view 41 <view
...@@ -41,6 +45,6 @@ ...@@ -41,6 +45,6 @@
41 hover-stay-time="70" 45 hover-stay-time="70"
42 > 46 >
43 <slot wx:if="{{ useActionSlot }}" name="action" /> 47 <slot wx:if="{{ useActionSlot }}" name="action" />
44 <view wx:else bind:tap="onCancel" class="cancel-class">取消</view> 48 <view wx:else bind:tap="onCancel" class="cancel-class">{{ actionText }}</view>
45 </view> 49 </view>
46 </view> 50 </view>
......
1 @import '../common/index.wxss';.van-search{padding:10px 16px;-webkit-align-items:center;align-items:center;box-sizing:border-box}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{padding-left:10px;background-color:#f7f8fa;border-radius:2px;-webkit-flex:1;flex:1}.van-search__content--round{border-radius:17px}.van-search__label{padding:0 5px;font-size:14px;line-height:34px;color:#333}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#999}.van-search--withaction{padding-right:0}.van-search input::-webkit-search-cancel-button,.van-search input::-webkit-search-decoration,.van-search input::-webkit-search-results-button,.van-search input::-webkit-search-results-decoration{display:none}.van-search__action{padding:0 10px;font-size:14px;line-height:34px;color:#333}.van-search__action--hover{background-color:#f2f3f5}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-search{-webkit-align-items:center;align-items:center;box-sizing:border-box;padding:10px 12px;padding:var(--search-padding,10px 12px)}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{-webkit-flex:1;flex:1;padding-left:8px;padding-left:var(--padding-xs,8px);border-radius:2px;border-radius:var(--border-radius-sm,2px);background-color:#f7f8fa;background-color:var(--search-background-color,#f7f8fa)}.van-search__content--round{border-radius:17px;border-radius:calc(var(--search-input-height, 34px)/2)}.van-search__label{padding:0 5px;padding:var(--search-label-padding,0 5px);font-size:14px;font-size:var(--search-label-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-label-color,#323233)}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#969799;color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{padding:0 8px;padding:var(--search-action-padding,0 8px);font-size:14px;font-size:var(--search-action-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-action-text-color,#323233)}.van-search__action--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 VantComponent({ 2 VantComponent({
3 classes: [
4 'active-class',
5 'disabled-class',
6 ],
3 relation: { 7 relation: {
4 type: 'ancestor', 8 type: 'ancestor',
5 name: 'badge-group' 9 name: 'sidebar',
10 linked(target) {
11 this.parent = target;
12 }
6 }, 13 },
7 props: { 14 props: {
15 dot: Boolean,
8 info: null, 16 info: null,
9 title: String 17 title: String,
18 disabled: Boolean
10 }, 19 },
11 methods: { 20 methods: {
12 onClick() { 21 onClick() {
13 const group = this.getRelationNodes('../badge-group/index')[0]; 22 const { parent } = this;
14 if (group) { 23 if (!parent || this.data.disabled) {
15 group.setActive(this); 24 return;
16 } 25 }
26 const index = parent.children.indexOf(this);
27 parent.setActive(index).then(() => {
28 this.$emit('click', index);
29 parent.$emit('change', index);
30 });
17 }, 31 },
18 setActive(active) { 32 setActive(selected) {
19 this.set({ active }); 33 return this.setData({ selected });
20 } 34 }
21 } 35 }
22 }); 36 });
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <view 3 <view
4 class="{{ utils.bem('badge', { active }) }} van-hairline custom-class" 4 class="{{ utils.bem('sidebar-item', { selected, disabled }) }} {{ selected ? 'active-class' : '' }} {{ disabled ? 'disabled-class' : '' }} custom-class"
5 hover-class="van-badge--hover" 5 hover-class="van-sidebar-item--hover"
6 hover-stay-time="70" 6 hover-stay-time="70"
7 bind:tap="onClick" 7 bind:tap="onClick"
8 > 8 >
9 <view class="van-badge__text"> 9 <view class="van-sidebar-item__text">
10 <van-info 10 <van-info
11 wx:if="{{ info !== null }}" 11 wx:if="{{ info !== null || dot }}"
12 dot="{{ dot }}"
12 info="{{ info }}" 13 info="{{ info }}"
13 custom-style="right: 4px" 14 custom-style="right: 4px"
14 /> 15 />
......
1 @import '../common/index.wxss';.van-sidebar-item{display:block;box-sizing:border-box;overflow:hidden;word-wrap:break-word;border-left:3px solid transparent;-webkit-user-select:none;user-select:none;padding:20px 12px 20px 8px;padding:var(--sidebar-padding,20px 12px 20px 8px);font-size:14px;font-size:var(--sidebar-font-size,14px);line-height:20px;line-height:var(--sidebar-line-height,20px);color:#323233;color:var(--sidebar-text-color,#323233);background-color:#fafafa;background-color:var(--sidebar-background-color,#fafafa)}.van-sidebar-item__text{position:relative;display:inline-block}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:#f2f3f5;background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{color:#323233;color:var(--sidebar-selected-text-color,#323233);font-weight:500;font-weight:var(--sidebar-selected-font-weight,500);border-color:#ee0a24;border-color:var(--sidebar-selected-border-color,#ee0a24)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:#fff;background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:#c8c9cc;color:var(--sidebar-disabled-text-color,#c8c9cc)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { isNumber } from '../common/utils';
3 VantComponent({ 2 VantComponent({
4 relation: { 3 relation: {
5 name: 'badge', 4 name: 'sidebar-item',
6 type: 'descendant', 5 type: 'descendant',
7 linked(target) { 6 linked(target) {
8 this.badges.push(target); 7 this.children.push(target);
9 this.setActive(); 8 this.setActive(this.data.activeKey);
10 }, 9 },
11 unlinked(target) { 10 unlinked(target) {
12 this.badges = this.badges.filter(item => item !== target); 11 this.items = this.children.filter((item) => item !== target);
13 this.setActive(); 12 this.setActive(this.data.activeKey);
14 } 13 }
15 }, 14 },
16 props: { 15 props: {
17 active: { 16 activeKey: {
18 type: Number, 17 type: Number,
19 value: 0 18 value: 0,
19 observer: 'setActive'
20 } 20 }
21 }, 21 },
22 watch: {
23 active: 'setActive'
24 },
25 beforeCreate() { 22 beforeCreate() {
26 this.badges = []; 23 this.children = [];
27 this.currentActive = -1; 24 this.currentActive = -1;
28 }, 25 },
29 methods: { 26 methods: {
30 setActive(badge) { 27 setActive(activeKey) {
31 let { active } = this.data; 28 const { children, currentActive } = this;
32 const { badges } = this; 29 if (!children.length) {
33 if (badge && !isNumber(badge)) { 30 return Promise.resolve();
34 active = badges.indexOf(badge);
35 }
36 if (active === this.currentActive) {
37 return;
38 } 31 }
39 if (this.currentActive !== -1 && badges[this.currentActive]) { 32 this.currentActive = activeKey;
40 this.$emit('change', active); 33 const stack = [];
41 badges[this.currentActive].setActive(false); 34 if (currentActive !== activeKey && children[currentActive]) {
35 stack.push(children[currentActive].setActive(false));
42 } 36 }
43 if (badges[active]) { 37 if (children[activeKey]) {
44 badges[active].setActive(true); 38 stack.push(children[activeKey].setActive(true));
45 this.currentActive = active;
46 } 39 }
40 return Promise.all(stack);
47 } 41 }
48 } 42 }
49 }); 43 });
......
1 <view class="van-badge-group van-hairline--top-bottom custom-class"> 1 <view class="van-sidebar van-hairline--top-bottom custom-class">
2 <slot /> 2 <slot />
3 </view> 3 </view>
......
1 @import '../common/index.wxss';.van-sidebar{width:85px;width:var(--sidebar-width,85px)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 row: {
5 type: Number,
6 value: 0
7 },
8 title: Boolean,
9 avatar: Boolean,
10 loading: {
11 type: Boolean,
12 value: true
13 },
14 animate: {
15 type: Boolean,
16 value: true
17 },
18 avatarSize: {
19 type: String,
20 value: '32px'
21 },
22 avatarShape: {
23 type: String,
24 value: 'round'
25 },
26 titleWidth: {
27 type: String,
28 value: '40%'
29 },
30 rowWidth: {
31 type: null,
32 value: '100%',
33 observer(val) {
34 this.setData({ isArray: val instanceof Array });
35 }
36 }
37 },
38 data: {
39 isArray: false
40 }
41 });
1 {
2 "component": true,
3 "usingComponents": {}
4 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 wx:if="{{ loading }}"
5 class="custom-class {{ utils.bem('skeleton', [{animate}]) }}"
6 >
7 <view
8 wx:if="{{ avatar }}"
9 class="{{ utils.bem('skeleton__avatar', [avatarShape])}}"
10 style="{{ 'width:' + avatarSize + ';height:' + avatarSize }}"
11 />
12 <view class="{{ utils.bem('skeleton__content')}}">
13 <view
14 wx:if="{{ title }}"
15 class="{{ utils.bem('skeleton__title') }}"
16 style="{{ 'width:' + titleWidth }}"
17 />
18 <view
19 wx:for="row"
20 wx:key="index"
21 wx:for-index="index"
22 class="{{ utils.bem('skeleton__row') }}"
23 style="{{ 'width:' + (isArray ? rowWidth[index] : rowWidth) }}"
24 />
25 </view>
26 </view>
27 <view wx:else class="{{ utils.bem('skeleton__content')}}">
28 <slot />
29 </view>
1 @import '../common/index.wxss';.van-skeleton{display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:0 16px;padding:var(--skeleton-padding,0 16px)}.van-skeleton__avatar{-webkit-flex-shrink:0;flex-shrink:0;margin-right:16px;margin-right:var(--padding-md,16px);background-color:#f2f3f5;background-color:var(--skeleton-avatar-background-color,#f2f3f5)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{-webkit-flex:1;flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:8px;padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{height:16px;height:var(--skeleton-row-height,16px);background-color:#f2f3f5;background-color:var(--skeleton-row-background-color,#f2f3f5)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:12px;margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{-webkit-animation:van-skeleton-blink 1.2s ease-in-out infinite;animation:van-skeleton-blink 1.2s ease-in-out infinite}@-webkit-keyframes van-skeleton-blink{50%{opacity:.6}}@keyframes van-skeleton-blink{50%{opacity:.6}}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch'; 2 import { touch } from '../mixins/touch';
3 import { addUnit } from '../common/utils';
3 VantComponent({ 4 VantComponent({
4 mixins: [touch], 5 mixins: [touch],
5 props: { 6 props: {
...@@ -24,7 +25,7 @@ VantComponent({ ...@@ -24,7 +25,7 @@ VantComponent({
24 value: 0 25 value: 0
25 }, 26 },
26 barHeight: { 27 barHeight: {
27 type: String, 28 type: null,
28 value: '2px' 29 value: '2px'
29 } 30 }
30 }, 31 },
...@@ -42,34 +43,50 @@ VantComponent({ ...@@ -42,34 +43,50 @@ VantComponent({
42 return; 43 return;
43 this.touchStart(event); 44 this.touchStart(event);
44 this.startValue = this.format(this.data.value); 45 this.startValue = this.format(this.data.value);
46 this.dragStatus = 'start';
45 }, 47 },
46 onTouchMove(event) { 48 onTouchMove(event) {
47 if (this.data.disabled) 49 if (this.data.disabled)
48 return; 50 return;
51 if (this.dragStatus === 'start') {
52 this.$emit('drag-start');
53 }
49 this.touchMove(event); 54 this.touchMove(event);
55 this.dragStatus = 'draging';
50 this.getRect('.van-slider').then((rect) => { 56 this.getRect('.van-slider').then((rect) => {
51 const diff = this.deltaX / rect.width * 100; 57 const diff = this.deltaX / rect.width * 100;
52 this.updateValue(this.startValue + diff, false, true); 58 this.newValue = this.startValue + diff;
59 this.updateValue(this.newValue, false, true);
53 }); 60 });
54 }, 61 },
55 onTouchEnd() { 62 onTouchEnd() {
56 if (this.data.disabled) 63 if (this.data.disabled)
57 return; 64 return;
58 this.updateValue(this.data.value, true); 65 if (this.dragStatus === 'draging') {
66 this.updateValue(this.newValue, true);
67 this.$emit('drag-end');
68 }
59 }, 69 },
60 onClick(event) { 70 onClick(event) {
61 if (this.data.disabled) 71 if (this.data.disabled)
62 return; 72 return;
73 const { min } = this.data;
63 this.getRect('.van-slider').then((rect) => { 74 this.getRect('.van-slider').then((rect) => {
64 const value = (event.detail.x - rect.left) / rect.width * 100; 75 const value = (event.detail.x - rect.left) / rect.width * this.getRange() + min;
65 this.updateValue(value, true); 76 this.updateValue(value, true);
66 }); 77 });
67 }, 78 },
68 updateValue(value, end, drag) { 79 updateValue(value, end, drag) {
69 value = this.format(value); 80 value = this.format(value);
70 this.set({ 81 const { barHeight, min } = this.data;
82 const width = `${((value - min) * 100) / this.getRange()}%`;
83 this.setData({
71 value, 84 value,
72 barStyle: `width: ${value}%; height: ${this.data.barHeight};` 85 barStyle: `
86 width: ${width};
87 height: ${addUnit(barHeight)};
88 ${drag ? 'transition: none;' : ''}
89 `,
73 }); 90 });
74 if (drag) { 91 if (drag) {
75 this.$emit('drag', { value }); 92 this.$emit('drag', { value });
...@@ -78,6 +95,10 @@ VantComponent({ ...@@ -78,6 +95,10 @@ VantComponent({
78 this.$emit('change', value); 95 this.$emit('change', value);
79 } 96 }
80 }, 97 },
98 getRange() {
99 const { max, min } = this.data;
100 return max - min;
101 },
81 format(value) { 102 format(value) {
82 const { max, min, step } = this.data; 103 const { max, min, step } = this.data;
83 return Math.round(Math.max(min, Math.min(value, max)) / step) * step; 104 return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
......
1 @import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;background-color:#e5e5e5}.van-slider__bar{position:relative;border-radius:inherit;background-color:#1989fa}.van-slider__button{width:20px;height:20px;border-radius:50%;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.5)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper:after{content:"";position:absolute;width:200%;height:200%;top:-50%;left:-50%}.van-slider--disabled{opacity:.3}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;border-radius:var(--border-radius-max,999px);background-color:#e5e5e5;background-color:var(--slider-inactive-background-color,#e5e5e5)}.van-slider:before{position:absolute;right:0;left:0;content:"";top:-8px;top:-var(--padding-xs,8px);bottom:-8px;bottom:-var(--padding-xs,8px)}.van-slider__bar{position:relative;border-radius:inherit;transition:width .2s;transition:width var(--animation-duration-fast,.2s);background-color:#1989fa;background-color:var(--slider-active-background-color,#1989fa)}.van-slider__button{width:24px;height:24px;border-radius:50%;box-shadow:0 1px 2px rgba(0,0,0,.5);background-color:#fff;background-color:var(--slider-button-background-color,#fff)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider--disabled{opacity:.5}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { addUnit, isDef } from '../common/utils';
3 const LONG_PRESS_START_TIME = 600;
4 const LONG_PRESS_INTERVAL = 200;
5 // add num and avoid float number
6 function add(num1, num2) {
7 const cardinal = Math.pow(10, 10);
8 return Math.round((num1 + num2) * cardinal) / cardinal;
9 }
2 VantComponent({ 10 VantComponent({
3 field: true, 11 field: true,
4 classes: [ 12 classes: ['input-class', 'plus-class', 'minus-class'],
5 'input-class',
6 'plus-class',
7 'minus-class'
8 ],
9 props: { 13 props: {
10 value: null, 14 value: null,
11 integer: Boolean, 15 integer: Boolean,
12 disabled: Boolean, 16 disabled: Boolean,
13 inputWidth: String, 17 inputWidth: null,
18 buttonSize: null,
14 asyncChange: Boolean, 19 asyncChange: Boolean,
15 disableInput: Boolean, 20 disableInput: Boolean,
21 decimalLength: {
22 type: Number,
23 value: null
24 },
16 min: { 25 min: {
17 type: null, 26 type: null,
18 value: 1 27 value: 1
...@@ -24,14 +33,14 @@ VantComponent({ ...@@ -24,14 +33,14 @@ VantComponent({
24 step: { 33 step: {
25 type: null, 34 type: null,
26 value: 1 35 value: 1
27 }
28 },
29 computed: {
30 minusDisabled() {
31 return this.data.disabled || this.data.value <= this.data.min;
32 }, 36 },
33 plusDisabled() { 37 showPlus: {
34 return this.data.disabled || this.data.value >= this.data.max; 38 type: Boolean,
39 value: true
40 },
41 showMinus: {
42 type: Boolean,
43 value: true
35 } 44 }
36 }, 45 },
37 watch: { 46 watch: {
...@@ -40,20 +49,39 @@ VantComponent({ ...@@ -40,20 +49,39 @@ VantComponent({
40 return; 49 return;
41 } 50 }
42 const newValue = this.range(value); 51 const newValue = this.range(value);
43 if (typeof newValue === 'number' && value !== newValue) { 52 if (typeof newValue === 'number' && +this.data.value !== newValue) {
44 this.set({ value: newValue }); 53 this.setData({ value: newValue });
45 } 54 }
55 },
56 inputWidth() {
57 this.set({
58 inputStyle: this.computeInputStyle()
59 });
60 },
61 buttonSize() {
62 this.set({
63 inputStyle: this.computeInputStyle(),
64 buttonStyle: this.computeButtonStyle()
65 });
46 } 66 }
47 }, 67 },
48 data: { 68 data: {
49 focus: false 69 focus: false,
70 inputStyle: '',
71 buttonStyle: ''
50 }, 72 },
51 created() { 73 created() {
52 this.set({ 74 this.setData({
53 value: this.range(this.data.value) 75 value: this.range(this.data.value)
54 }); 76 });
55 }, 77 },
56 methods: { 78 methods: {
79 isDisabled(type) {
80 if (type === 'plus') {
81 return this.data.disabled || this.data.value >= this.data.max;
82 }
83 return this.data.disabled || this.data.value <= this.data.min;
84 },
57 onFocus(event) { 85 onFocus(event) {
58 this.$emit('focus', event.detail); 86 this.$emit('focus', event.detail);
59 }, 87 },
...@@ -64,33 +92,79 @@ VantComponent({ ...@@ -64,33 +92,79 @@ VantComponent({
64 }, 92 },
65 // limit value range 93 // limit value range
66 range(value) { 94 range(value) {
67 return Math.max(Math.min(this.data.max, value), this.data.min); 95 value = String(value).replace(/[^0-9.-]/g, '');
96 // format range
97 value = value === '' ? 0 : +value;
98 value = Math.max(Math.min(this.data.max, value), this.data.min);
99 // format decimal
100 if (isDef(this.data.decimalLength)) {
101 value = value.toFixed(this.data.decimalLength);
102 }
103 return value;
68 }, 104 },
69 onInput(event) { 105 onInput(event) {
70 const { value = '' } = event.detail || {}; 106 const { value = '' } = event.detail || {};
71 this.triggerInput(value); 107 this.triggerInput(value);
72 }, 108 },
73 onChange(type) { 109 onChange() {
74 if (this.data[`${type}Disabled`]) { 110 const { type } = this;
111 if (this.isDisabled(type)) {
75 this.$emit('overlimit', type); 112 this.$emit('overlimit', type);
76 return; 113 return;
77 } 114 }
78 const diff = type === 'minus' ? -this.data.step : +this.data.step; 115 const diff = type === 'minus' ? -this.data.step : +this.data.step;
79 const value = Math.round((this.data.value + diff) * 100) / 100; 116 const value = add(+this.data.value, diff);
80 this.triggerInput(this.range(value)); 117 this.triggerInput(this.range(value));
81 this.$emit(type); 118 this.$emit(type);
82 }, 119 },
83 onMinus() { 120 longPressStep() {
84 this.onChange('minus'); 121 this.longPressTimer = setTimeout(() => {
122 this.onChange();
123 this.longPressStep();
124 }, LONG_PRESS_INTERVAL);
85 }, 125 },
86 onPlus() { 126 onTap(event) {
87 this.onChange('plus'); 127 const { type } = event.currentTarget.dataset;
128 this.type = type;
129 this.onChange();
130 },
131 onTouchStart(event) {
132 clearTimeout(this.longPressTimer);
133 const { type } = event.currentTarget.dataset;
134 this.type = type;
135 this.isLongPress = false;
136 this.longPressTimer = setTimeout(() => {
137 this.isLongPress = true;
138 this.onChange();
139 this.longPressStep();
140 }, LONG_PRESS_START_TIME);
141 },
142 onTouchEnd() {
143 clearTimeout(this.longPressTimer);
88 }, 144 },
89 triggerInput(value) { 145 triggerInput(value) {
90 this.set({ 146 this.setData({
91 value: this.data.asyncChange ? this.data.value : value 147 value: this.data.asyncChange ? this.data.value : value
92 }); 148 });
93 this.$emit('change', value); 149 this.$emit('change', value);
150 },
151 computeInputStyle() {
152 let style = '';
153 if (this.data.inputWidth) {
154 style = `width: ${addUnit(this.data.inputWidth)};`;
155 }
156 if (this.data.buttonSize) {
157 style += `height: ${addUnit(this.data.buttonSize)};`;
158 }
159 return style;
160 },
161 computeButtonStyle() {
162 let style = '';
163 const size = addUnit(this.data.buttonSize);
164 if (this.data.buttonSize) {
165 style = `width: ${size};height: ${size};`;
166 }
167 return style;
94 } 168 }
95 } 169 }
96 }); 170 });
......
...@@ -2,15 +2,20 @@ ...@@ -2,15 +2,20 @@
2 2
3 <view class="van-stepper custom-class"> 3 <view class="van-stepper custom-class">
4 <view 4 <view
5 class="minus-class {{ utils.bem('stepper__minus', { disabled: minusDisabled }) }}" 5 wx:if="{{ showMinus }}"
6 data-type="minus"
7 style="{{ buttonStyle }}"
8 class="minus-class {{ utils.bem('stepper__minus', { disabled: disabled || value <= min }) }}"
6 hover-class="van-stepper__minus--hover" 9 hover-class="van-stepper__minus--hover"
7 hover-stay-time="70" 10 hover-stay-time="70"
8 bind:tap="onMinus" 11 bind:tap="onTap"
12 bind:touchstart="onTouchStart"
13 bind:touchend="onTouchEnd"
9 /> 14 />
10 <input 15 <input
11 type="{{ integer ? 'number' : 'digit' }}" 16 type="{{ integer ? 'number' : 'digit' }}"
12 class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}" 17 class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
13 style="{{ inputWidth ? 'width: ' + inputWidth : '' }}" 18 style="{{ inputStyle }}"
14 value="{{ value }}" 19 value="{{ value }}"
15 focus="{{ focus }}" 20 focus="{{ focus }}"
16 disabled="{{ disabled || disableInput }}" 21 disabled="{{ disabled || disableInput }}"
...@@ -19,9 +24,14 @@ ...@@ -19,9 +24,14 @@
19 bind:blur="onBlur" 24 bind:blur="onBlur"
20 /> 25 />
21 <view 26 <view
22 class="plus-class {{ utils.bem('stepper__plus', { disabled: plusDisabled }) }}" 27 wx:if="{{ showPlus }}"
28 data-type="plus"
29 style="{{ buttonStyle }}"
30 class="plus-class {{ utils.bem('stepper__plus', { disabled: disabled || value >= max }) }}"
23 hover-class="van-stepper__plus--hover" 31 hover-class="van-stepper__plus--hover"
24 hover-stay-time="70" 32 hover-stay-time="70"
25 bind:tap="onPlus" 33 bind:tap="onTap"
34 bind:touchstart="onTouchStart"
35 bind:touchend="onTouchEnd"
26 /> 36 />
27 </view> 37 </view>
......
1 @import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;width:28px;height:28px;padding:5px;margin:1px;vertical-align:middle;background-color:#f2f3f5;border:0;box-sizing:border-box}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:#333;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8}.van-stepper__minus--disabled,.van-stepper__plus--disabled{background-color:#f7f8fa}.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#c9c9c9}.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa}.van-stepper__minus{border-radius:4px 0 0 4px}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0}.van-stepper__input{display:inline-block;width:30px;height:26px;padding:1px;margin:1px;font-size:14px;color:#333;text-align:center;vertical-align:middle;background-color:#f2f3f5;border:0;border-width:1px 0;border-radius:0;box-sizing:initial;-webkit-appearance:none}.van-stepper__input--disabled{color:#c9c9c9;background-color:#f2f3f5}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;box-sizing:border-box;margin:1px;vertical-align:middle;border:0;background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);color:#323233;color:var(--stepper-button-icon-color,#323233);width:28px;width:var(--stepper-input-height,28px);height:28px;height:var(--stepper-input-height,28px);padding:4px;padding:var(--padding-base,4px)}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;content:"";background-color:#323233;background-color:var(--text-color,#323233)}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8;background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:#c8c9cc;color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#f7f8fa;background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:4px 0 0 4px;border-radius:var(--stepper-border-radius,4px) 0 0 var(--stepper-border-radius,4px)}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0;border-radius:0 var(--stepper-border-radius,4px) var(--stepper-border-radius,4px) 0}.van-stepper__input{display:inline-block;box-sizing:border-box;min-height:0;margin:1px;padding:1px;text-align:center;vertical-align:middle;border:0;border-width:1px 0;border-radius:0;-webkit-appearance:none;font-size:14px;font-size:var(--stepper-input-font-size,14px);color:#323233;color:var(--stepper-input-text-color,#323233);background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);width:32px;width:var(--stepper-input-width,32px);height:28px;height:var(--stepper-input-height,28px)}.van-stepper__input--disabled{color:#c8c9cc;color:var(--stepper-input-disabled-text-color,#c8c9cc);background-color:#f2f3f5;background-color:var(--stepper-input-disabled-background-color,#f2f3f5)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -12,6 +12,11 @@ VantComponent({ ...@@ -12,6 +12,11 @@ VantComponent({
12 activeColor: { 12 activeColor: {
13 type: String, 13 type: String,
14 value: GREEN 14 value: GREEN
15 } 15 },
16 activeIcon: {
17 type: String,
18 value: 'checked'
19 },
20 inactiveIcon: String
16 } 21 }
17 }); 22 });
......
...@@ -12,10 +12,26 @@ ...@@ -12,10 +12,26 @@
12 <view>{{ item.desc }}</view> 12 <view>{{ item.desc }}</view>
13 </view> 13 </view>
14 <view class="van-step__circle-container"> 14 <view class="van-step__circle-container">
15 <view class="van-step__circle" wx:if="{{ index !== active }}" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" /> 15 <block wx:if="{{ index !== active }}">
16 <van-icon wx:else name="checked" color="{{ activeColor }}" custom-class="van-step__active" /> 16 <van-icon
17 wx:if="{{ inactiveIcon }}"
18 color="#969799"
19 name="{{ inactiveIcon }}"
20 custom-class="van-step__icon"
21 />
22 <view
23 wx:else
24 class="van-step__circle"
25 style="{{ index < active ? 'background-color: ' + activeColor : '' }}"
26 />
27 </block>
28
29 <van-icon wx:else name="{{ activeIcon }}" color="{{ activeColor }}" custom-class="van-step__icon" />
17 </view> 30 </view>
18 <view wx:if="{{ index !== steps.length - 1 }}" class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" /> 31 <view
32 wx:if="{{ index !== steps.length - 1 }}"
33 class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}"
34 />
19 </view> 35 </view>
20 </view> 36 </view>
21 </view> 37 </view>
......
1 @import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;color:#999}.van-step--finish{color:#333}.van-step__circle{width:5px;height:5px;background-color:#999;border-radius:50%}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;padding:0 8px;background-color:#fff;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0)}.van-step--horizontal .van-step__title{display:inline-block;font-size:12px;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;background-color:#eee;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:#333}.van-step--horizontal.van-step--process .van-step__active{display:block;font-size:12px;line-height:1}.van-step--vertical{padding:10px 10px 10px 0;font-size:14px;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;background-color:#fff;content:""}.van-step--vertical .van-step__active,.van-step--vertical .van-step__circle,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__active{font-size:12px;line-height:1}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;background-color:#eee;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff;background-color:var(--steps-background-color,#fff)}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;font-size:var(--step-font-size,14px);color:#969799;color:var(--step-text-color,#969799)}.van-step--finish{color:#323233;color:var(--step-finish-text-color,#323233)}.van-step__circle{border-radius:50%;width:5px;width:var(--step-circle-size,5px);height:5px;height:var(--step-circle-size,5px);background-color:#969799;background-color:var(--step-circle-color,#969799)}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0);background-color:#fff;background-color:var(--white,#fff);padding:0 8px;padding:0 var(--padding-xs,8px)}.van-step--horizontal .van-step__title{display:inline-block;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);font-size:12px;font-size:var(--step-horizontal-title-font-size,12px)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0);background-color:#ebedf0;background-color:var(--step-line-color,#ebedf0)}.van-step--horizontal.van-step--process{color:#323233;color:var(--step-process-text-color,#323233)}.van-step--horizontal.van-step--process .van-step__icon{display:block;line-height:1;font-size:12px;font-size:var(--step-icon-size,12px)}.van-step--vertical{padding:10px 10px 10px 0;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;content:"";background-color:#fff;background-color:var(--white,#fff)}.van-step--vertical .van-step__circle,.van-step--vertical .van-step__icon,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__icon{line-height:1;font-size:12px;font-size:var(--step-icon-size,12px)}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);background-color:#ebedf0;background-color:var(--step-line-color,#ebedf0)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component';
2 const ROOT_ELEMENT = '.van-sticky';
3 VantComponent({
4 props: {
5 zIndex: {
6 type: Number,
7 value: 99
8 },
9 offsetTop: {
10 type: Number,
11 value: 0,
12 observer: 'observeContent'
13 },
14 disabled: {
15 type: Boolean,
16 observer(value) {
17 if (!this.mounted) {
18 return;
19 }
20 value ? this.disconnectObserver() : this.initObserver();
21 }
22 },
23 container: {
24 type: null,
25 observer(target) {
26 if (typeof target !== 'function' || !this.data.height) {
27 return;
28 }
29 this.observeContainer();
30 }
31 }
32 },
33 data: {
34 wrapStyle: '',
35 containerStyle: ''
36 },
37 methods: {
38 setStyle() {
39 const { offsetTop, height, fixed, zIndex } = this.data;
40 if (fixed) {
41 this.setData({
42 wrapStyle: `top: ${offsetTop}px;`,
43 containerStyle: `height: ${height}px; z-index: ${zIndex};`
44 });
45 }
46 else {
47 this.setData({
48 wrapStyle: '',
49 containerStyle: ''
50 });
51 }
52 },
53 getContainerRect() {
54 const nodesRef = this.data.container();
55 return new Promise(resolve => nodesRef.boundingClientRect(resolve).exec());
56 },
57 initObserver() {
58 this.disconnectObserver();
59 this.getRect(ROOT_ELEMENT).then((rect) => {
60 this.setData({ height: rect.height });
61 wx.nextTick(() => {
62 this.observeContent();
63 this.observeContainer();
64 });
65 });
66 },
67 disconnectObserver(observerName) {
68 if (observerName) {
69 const observer = this[observerName];
70 observer && observer.disconnect();
71 }
72 else {
73 this.contentObserver && this.contentObserver.disconnect();
74 this.containerObserver && this.containerObserver.disconnect();
75 }
76 },
77 observeContent() {
78 const { offsetTop } = this.data;
79 this.disconnectObserver('contentObserver');
80 const contentObserver = this.createIntersectionObserver({
81 thresholds: [0, 1]
82 });
83 this.contentObserver = contentObserver;
84 contentObserver.relativeToViewport({ top: -offsetTop });
85 contentObserver.observe(ROOT_ELEMENT, res => {
86 if (this.data.disabled) {
87 return;
88 }
89 this.setFixed(res.boundingClientRect.top);
90 });
91 },
92 observeContainer() {
93 if (typeof this.data.container !== 'function') {
94 return;
95 }
96 const { height } = this.data;
97 this.getContainerRect().then((rect) => {
98 this.containerHeight = rect.height;
99 this.disconnectObserver('containerObserver');
100 const containerObserver = this.createIntersectionObserver({
101 thresholds: [0, 1]
102 });
103 this.containerObserver = containerObserver;
104 containerObserver.relativeToViewport({
105 top: this.containerHeight - height
106 });
107 containerObserver.observe(ROOT_ELEMENT, res => {
108 if (this.data.disabled) {
109 return;
110 }
111 this.setFixed(res.boundingClientRect.top);
112 });
113 });
114 },
115 setFixed(top) {
116 const { offsetTop, height } = this.data;
117 const { containerHeight } = this;
118 const fixed = containerHeight && height
119 ? top > height - containerHeight && top < offsetTop
120 : top < offsetTop;
121 this.$emit('scroll', {
122 scrollTop: top,
123 isFixed: fixed
124 });
125 this.setData({ fixed });
126 wx.nextTick(() => {
127 this.setStyle();
128 });
129 }
130 },
131 mounted() {
132 this.mounted = true;
133 if (!this.data.disabled) {
134 this.initObserver();
135 }
136 },
137 destroyed() {
138 this.disconnectObserver();
139 }
140 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class van-sticky" style="{{ containerStyle }}">
4 <view class="{{ utils.bem('sticky-wrap', { fixed }) }}" style="{{ wrapStyle }}">
5 <slot />
6 </view>
7 </view>
1 @import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{position:fixed;right:0;left:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({ 2 VantComponent({
4 mixins: [safeArea()],
5 classes: [ 3 classes: [
6 'bar-class', 4 'bar-class',
7 'price-class', 5 'price-class',
8 'button-class' 6 'button-class'
9 ], 7 ],
10 props: { 8 props: {
11 tip: null, 9 tip: {
10 type: null,
11 observer: 'updateTip'
12 },
13 tipIcon: String,
12 type: Number, 14 type: Number,
13 price: null, 15 price: {
16 type: null,
17 observer: 'updatePrice'
18 },
14 label: String, 19 label: String,
15 loading: Boolean, 20 loading: Boolean,
16 disabled: Boolean, 21 disabled: Boolean,
...@@ -22,21 +27,29 @@ VantComponent({ ...@@ -22,21 +27,29 @@ VantComponent({
22 buttonType: { 27 buttonType: {
23 type: String, 28 type: String,
24 value: 'danger' 29 value: 'danger'
25 }
26 },
27 computed: {
28 hasPrice() {
29 return typeof this.data.price === 'number';
30 }, 30 },
31 priceStr() { 31 decimalLength: {
32 return (this.data.price / 100).toFixed(2); 32 type: Number,
33 value: 2,
34 observer: 'updatePrice'
33 }, 35 },
34 tipStr() { 36 suffixLabel: String,
35 const { tip } = this.data; 37 safeAreaInsetBottom: {
36 return typeof tip === 'string' ? tip : ''; 38 type: Boolean,
39 value: true
37 } 40 }
38 }, 41 },
39 methods: { 42 methods: {
43 updatePrice() {
44 const { price, decimalLength } = this.data;
45 this.setData({
46 hasPrice: typeof price === 'number',
47 priceStr: (price / 100).toFixed(decimalLength)
48 });
49 },
50 updateTip() {
51 this.setData({ hasTip: typeof this.data.tip === 'string' });
52 },
40 onSubmit(event) { 53 onSubmit(event) {
41 this.$emit('submit', event.detail); 54 this.$emit('submit', event.detail);
42 } 55 }
......
1 { 1 {
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-button": "../button/index" 4 "van-button": "../button/index",
5 "van-icon": "../icon/index"
5 } 6 }
6 } 7 }
......
...@@ -3,19 +3,28 @@ ...@@ -3,19 +3,28 @@
3 <view class="van-submit-bar custom-class"> 3 <view class="van-submit-bar custom-class">
4 <slot name="top" /> 4 <slot name="top" />
5 5
6 <view wx:if="{{ tip }}" class="van-submit-bar__tip"> 6 <view class="van-submit-bar__tip">
7 {{ tipStr }}<slot name="tip" /> 7 <van-icon
8 wx:if="{{ tipIcon }}"
9 size="12px"
10 name="{{ tipIcon }}"
11 custom-class="van-submit-bar__tip-icon"
12 />
13 <view wx:if="{{ hasTip }}" class="van-submit-bar__tip-text">
14 {{ tip }}
15 </view>
16 <slot name="tip" />
8 </view> 17 </view>
9 18
10 <view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom && isIPhoneX }) }}"> 19 <view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom }) }}">
11 <slot /> 20 <slot />
12 <view class="van-submit-bar__text"> 21 <view wx:if="{{ hasPrice }}" class="van-submit-bar__text">
13 <block wx:if="{{ hasPrice }}"> 22 <text>{{ label || '合计:' }}</text>
14 <text>{{ label || '合计:' }}</text> 23 <text class="van-submit-bar__price price-class">
15 <text class="van-submit-bar__price price-class"> 24 <text class="van-submit-bar__currency">{{ currency }} </text>
16 <text class="van-submit-bar__currency">{{ currency }}</text> {{ priceStr }} 25 <text>{{ priceStr }}</text>
17 </text> 26 </text>
18 </block> 27 <text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text>
19 </view> 28 </view>
20 <van-button 29 <van-button
21 square 30 square
......
1 @import '../common/index.wxss';.van-submit-bar{z-index:100;position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none}.van-submit-bar__tip{padding:10px;color:#f56723;font-size:12px;line-height:18px;background-color:#fff7cc}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:50px;background-color:#fff;font-size:14px}.van-submit-bar__bar--safe{padding-bottom:34px}.van-submit-bar__text{-webkit-flex:1;flex:1;color:#333;font-weight:500;text-align:right}.van-submit-bar__price{color:#f44;font-size:18px;padding-right:12px}.van-submit-bar__currency{font-size:14px}.van-submit-bar__button button{width:110px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-submit-bar{position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none;z-index:100;z-index:var(--submit-bar-z-index,100);background-color:#fff;background-color:var(--submit-bar-background-color,#fff)}.van-submit-bar__tip{padding:10px;padding:var(--submit-bar-tip-padding,10px);color:#f56723;color:var(--submit-bar-tip-color,#f56723);font-size:12px;font-size:var(--submit-bar-tip-font-size,12px);line-height:1.5;line-height:var(--submit-bar-tip-line-height,1.5);background-color:#fff7cc;background-color:var(--submit-bar-tip-background-color,#fff7cc)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{width:12px;height:12px;margin-right:4px;vertical-align:middle;font-size:12px;font-size:var(--submit-bar-tip-icon-size,12px);min-width:18px;min-width:calc(var(--submit-bar-tip-icon-size, 12px)*1.5)}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end;height:50px;height:var(--submit-bar-height,50px);font-size:14px;font-size:var(--submit-bar-text-font-size,14px);background-color:#fff;background-color:var(--submit-bar-background-color,#fff)}.van-submit-bar__bar--safe{padding-bottom:env(safe-area-inset-bottom)}.van-submit-bar__text{-webkit-flex:1;flex:1;text-align:right;color:#323233;color:var(--submit-bar-text-color,#323233);padding-right:12px;padding-right:var(--padding-sm,12px);font-weight:500;font-weight:var(--font-weight-bold,500)}.van-submit-bar__price{color:#ee0a24;color:var(--submit-bar-price-color,#ee0a24);font-size:18px;font-size:var(--submit-bar-price-font-size,18px)}.van-submit-bar__currency{font-size:14px;font-size:var(--submit-bar-currency-font-size,14px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{width:110px;width:var(--submit-bar-button-width,110px)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch'; 2 import { touch } from '../mixins/touch';
3 const THRESHOLD = 0.3; 3 const THRESHOLD = 0.3;
4 let ARRAY = [];
4 VantComponent({ 5 VantComponent({
5 props: { 6 props: {
6 disabled: Boolean, 7 disabled: Boolean,
...@@ -12,14 +13,22 @@ VantComponent({ ...@@ -12,14 +13,22 @@ VantComponent({
12 type: Number, 13 type: Number,
13 value: 0 14 value: 0
14 }, 15 },
15 asyncClose: Boolean 16 asyncClose: Boolean,
17 name: {
18 type: [Number, String],
19 value: ''
20 }
16 }, 21 },
17 mixins: [touch], 22 mixins: [touch],
18 data: { 23 data: {
19 catchMove: true 24 catchMove: false
20 }, 25 },
21 created() { 26 created() {
22 this.offset = 0; 27 this.offset = 0;
28 ARRAY.push(this);
29 },
30 destroyed() {
31 ARRAY = ARRAY.filter(item => item !== this);
23 }, 32 },
24 methods: { 33 methods: {
25 open(position) { 34 open(position) {
...@@ -35,8 +44,8 @@ VantComponent({ ...@@ -35,8 +44,8 @@ VantComponent({
35 const transform = `translate3d(${offset}px, 0, 0)`; 44 const transform = `translate3d(${offset}px, 0, 0)`;
36 const transition = this.draging 45 const transition = this.draging
37 ? 'none' 46 ? 'none'
38 : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'; 47 : 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
39 this.set({ 48 this.setData({
40 wrapperStyle: ` 49 wrapperStyle: `
41 -webkit-transform: ${transform}; 50 -webkit-transform: ${transform};
42 -webkit-transition: ${transition}; 51 -webkit-transition: ${transition};
...@@ -57,11 +66,17 @@ VantComponent({ ...@@ -57,11 +66,17 @@ VantComponent({
57 else { 66 else {
58 this.swipeMove(0); 67 this.swipeMove(0);
59 } 68 }
69 this.setData({ catchMove: false });
60 }, 70 },
61 startDrag(event) { 71 startDrag(event) {
62 if (this.data.disabled) { 72 if (this.data.disabled) {
63 return; 73 return;
64 } 74 }
75 ARRAY.forEach(item => {
76 if (item !== this) {
77 item.close();
78 }
79 });
65 this.draging = true; 80 this.draging = true;
66 this.startOffset = this.offset; 81 this.startOffset = this.offset;
67 this.firstDirection = ''; 82 this.firstDirection = '';
...@@ -75,7 +90,7 @@ VantComponent({ ...@@ -75,7 +90,7 @@ VantComponent({
75 this.touchMove(event); 90 this.touchMove(event);
76 if (!this.firstDirection) { 91 if (!this.firstDirection) {
77 this.firstDirection = this.direction; 92 this.firstDirection = this.direction;
78 this.set({ catchMove: this.firstDirection === 'horizontal' }); 93 this.setData({ catchMove: this.firstDirection === 'horizontal' });
79 } 94 }
80 if (this.firstDirection === 'vertical') { 95 if (this.firstDirection === 'vertical') {
81 return; 96 return;
...@@ -102,7 +117,7 @@ VantComponent({ ...@@ -102,7 +117,7 @@ VantComponent({
102 return; 117 return;
103 } 118 }
104 if (this.data.asyncClose) { 119 if (this.data.asyncClose) {
105 this.$emit('close', { position, instance: this }); 120 this.$emit('close', { position, instance: this, name: this.data.name });
106 } 121 }
107 else { 122 else {
108 this.swipeMove(0); 123 this.swipeMove(0);
......
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 props: {
5 value: null,
6 title: String,
7 border: Boolean,
8 checked: Boolean,
9 loading: Boolean,
10 disabled: Boolean,
11 activeColor: String,
12 inactiveColor: String,
13 size: {
14 type: String,
15 value: '24px'
16 },
17 activeValue: {
18 type: null,
19 value: true
20 },
21 inactiveValue: {
22 type: null,
23 value: false
24 }
25 },
26 watch: {
27 checked(value) {
28 this.set({ value });
29 }
30 },
31 created() {
32 this.set({ value: this.data.checked });
33 },
34 methods: {
35 onChange(event) {
36 this.$emit('change', event.detail);
37 }
38 }
39 });
1 <van-cell
2 center
3 title="{{ title }}"
4 border="{{ border }}"
5 custom-class="van-switch-cell"
6 >
7 <van-switch
8 size="{{ size }}"
9 checked="{{ checked }}"
10 loading="{{ loading }}"
11 disabled="{{ disabled }}"
12 active-color="{{ activeColor }}"
13 inactive-color="{{ inactiveColor }}"
14 active-value="{{ activeValue }}"
15 inactive-value="{{ inactiveValue }}"
16 custom-class="van-switch-cell__switch"
17 bind:change="onChange"
18 />
19 </van-cell>
1 @import '../common/index.wxss';.van-switch-cell{padding-top:9px;padding-bottom:9px}.van-switch-cell__switch{vertical-align:middle}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { BLUE, GRAY_DARK } from '../common/color';
2 VantComponent({ 3 VantComponent({
3 field: true, 4 field: true,
4 classes: ['node-class'], 5 classes: ['node-class'],
...@@ -23,13 +24,20 @@ VantComponent({ ...@@ -23,13 +24,20 @@ VantComponent({
23 }, 24 },
24 watch: { 25 watch: {
25 checked(value) { 26 checked(value) {
26 this.set({ value }); 27 const loadingColor = this.getLoadingColor(value);
28 this.setData({ value, loadingColor });
27 } 29 }
28 }, 30 },
29 created() { 31 created() {
30 this.set({ value: this.data.checked }); 32 const { checked: value } = this.data;
33 const loadingColor = this.getLoadingColor(value);
34 this.setData({ value, loadingColor });
31 }, 35 },
32 methods: { 36 methods: {
37 getLoadingColor(checked) {
38 const { activeColor, inactiveColor } = this.data;
39 return checked ? activeColor || BLUE : inactiveColor || GRAY_DARK;
40 },
33 onClick() { 41 onClick() {
34 const { activeValue, inactiveValue } = this.data; 42 const { activeValue, inactiveValue } = this.data;
35 if (!this.data.disabled && !this.data.loading) { 43 if (!this.data.disabled && !this.data.loading) {
......
...@@ -6,6 +6,6 @@ ...@@ -6,6 +6,6 @@
6 bind:tap="onClick" 6 bind:tap="onClick"
7 > 7 >
8 <view class="van-switch__node node-class"> 8 <view class="van-switch__node node-class">
9 <van-loading wx:if="{{ loading }}" size="50%" custom-class="van-switch__loading" /> 9 <van-loading wx:if="{{ loading }}" color="{{ loadingColor }}" custom-class="van-switch__loading" />
10 </view> 10 </view>
11 </view> 11 </view>
......
1 @import '../common/index.wxss';.van-switch{display:inline-block;position:relative;width:2em;border:1px solid rgba(0,0,0,.1);border-radius:1em;box-sizing:initial;transition:background-color .3s}.van-switch,.van-switch__node{height:1em;background-color:#fff}.van-switch__node{top:0;left:0;position:absolute;border-radius:100%;width:1em;z-index:1;transition:.3s;box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05)}.van-switch__loading{top:25%;left:25%;position:absolute!important}.van-switch--on{background-color:#1989fa}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em)}.van-switch--disabled{opacity:.4}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-switch{position:relative;display:inline-block;box-sizing:initial;width:2em;width:var(--switch-width,2em);height:1em;height:var(--switch-height,1em);background-color:#fff;background-color:var(--switch-background-color,#fff);border:1px solid rgba(0,0,0,.1);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:1em;border-radius:var(--switch-node-size,1em);transition:background-color .3s;transition:background-color var(--switch-transition-duration,.3s)}.van-switch__node{position:absolute;top:0;left:0;border-radius:100%;z-index:1;z-index:var(--switch-node-z-index,1);width:1em;width:var(--switch-node-size,1em);height:1em;height:var(--switch-node-size,1em);background-color:#fff;background-color:var(--switch-node-background-color,#fff);box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05);box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));transition:-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05),-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05),-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05)}.van-switch__loading{position:absolute!important;top:25%;left:25%;width:50%;height:50%}.van-switch--on{background-color:#1989fa;background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em);-webkit-transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)));transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:.4;opacity:var(--switch-disabled-opacity,.4)}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -2,20 +2,27 @@ import { VantComponent } from '../common/component'; ...@@ -2,20 +2,27 @@ import { VantComponent } from '../common/component';
2 VantComponent({ 2 VantComponent({
3 relation: { 3 relation: {
4 name: 'tabs', 4 name: 'tabs',
5 type: 'ancestor' 5 type: 'ancestor',
6 linked(target) {
7 this.parent = target;
8 },
9 unlinked() {
10 this.parent = null;
11 }
6 }, 12 },
7 props: { 13 props: {
8 dot: Boolean, 14 dot: Boolean,
9 info: null, 15 info: null,
10 title: String, 16 title: String,
11 disabled: Boolean, 17 disabled: Boolean,
12 titleStyle: String 18 titleStyle: String,
19 name: {
20 type: [Number, String],
21 value: '',
22 }
13 }, 23 },
14 data: { 24 data: {
15 width: null, 25 active: false
16 inited: false,
17 active: false,
18 animated: false
19 }, 26 },
20 watch: { 27 watch: {
21 title: 'update', 28 title: 'update',
...@@ -25,10 +32,23 @@ VantComponent({ ...@@ -25,10 +32,23 @@ VantComponent({
25 titleStyle: 'update' 32 titleStyle: 'update'
26 }, 33 },
27 methods: { 34 methods: {
35 getComputedName() {
36 if (this.data.name !== '') {
37 return this.data.name;
38 }
39 return this.index;
40 },
41 updateRender(active, parent) {
42 const { data: parentData } = parent;
43 this.inited = this.inited || active;
44 this.setData({
45 active,
46 shouldRender: this.inited || !parentData.lazyRender
47 });
48 },
28 update() { 49 update() {
29 const parent = this.getRelationNodes('../tabs/index')[0]; 50 if (this.parent) {
30 if (parent) { 51 this.parent.updateTabs();
31 parent.updateTabs();
32 } 52 }
33 } 53 }
34 } 54 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <view 3 <view
4 wx:if="{{ animated || inited }}" 4 wx:if="{{ shouldRender }}"
5 class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}" 5 class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
6 style="{{ animated || active ? '' : 'display: none;' }} {{ width ? 'width:' + width + 'px;' : '' }}"
7 > 6 >
8 <slot /> 7 <slot />
9 </view> 8 </view>
......
1 @import '../common/index.wxss';.van-tab__pane{box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';:host{-webkit-flex-shrink:0;flex-shrink:0;width:100%}.van-tab__pane,:host{box-sizing:border-box}.van-tab__pane{overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -2,15 +2,13 @@ import { VantComponent } from '../common/component'; ...@@ -2,15 +2,13 @@ import { VantComponent } from '../common/component';
2 VantComponent({ 2 VantComponent({
3 props: { 3 props: {
4 info: null, 4 info: null,
5 name: null,
5 icon: String, 6 icon: String,
6 dot: Boolean 7 dot: Boolean
7 }, 8 },
8 relation: { 9 relation: {
9 name: 'tabbar', 10 name: 'tabbar',
10 type: 'ancestor', 11 type: 'ancestor'
11 linked(target) {
12 this.parent = target;
13 }
14 }, 12 },
15 data: { 13 data: {
16 active: false 14 active: false
...@@ -22,11 +20,28 @@ VantComponent({ ...@@ -22,11 +20,28 @@ VantComponent({
22 } 20 }
23 this.$emit('click'); 21 this.$emit('click');
24 }, 22 },
25 setActive({ active, color }) { 23 updateFromParent() {
26 if (this.data.active !== active) { 24 const { parent } = this;
27 return this.set({ active, color }); 25 if (!parent) {
26 return;
27 }
28 const index = parent.children.indexOf(this);
29 const parentData = parent.data;
30 const { data } = this;
31 const active = (data.name || index) === parentData.active;
32 const patch = {};
33 if (active !== data.active) {
34 patch.active = active;
35 }
36 if (parentData.activeColor !== data.activeColor) {
37 patch.activeColor = parentData.activeColor;
38 }
39 if (parentData.inactiveColor !== data.inactiveColor) {
40 patch.inactiveColor = parentData.inactiveColor;
28 } 41 }
29 return Promise.resolve(); 42 return Object.keys(patch).length > 0
43 ? this.set(patch)
44 : Promise.resolve();
30 } 45 }
31 } 46 }
32 }); 47 });
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
2 2
3 <view 3 <view
4 class="{{ utils.bem('tabbar-item', { active }) }} custom-class" 4 class="{{ utils.bem('tabbar-item', { active }) }} custom-class"
5 style="{{ active && color ? 'color: ' + color : '' }}" 5 style="color: {{ active ? activeColor : inactiveColor }}"
6 bind:tap="onClick" 6 bind:tap="onClick"
7 > 7 >
8 <view class="{{ utils.bem('tabbar-item__icon', { dot }) }}"> 8 <view class="van-tabbar-item__icon">
9 <van-icon 9 <van-icon
10 wx:if="{{ icon }}" 10 wx:if="{{ icon }}"
11 name="{{ icon }}" 11 name="{{ icon }}"
12 customStyle="display: block" 12 custom-class="van-tabbar-item__icon__inner"
13 /> 13 />
14 <block wx:else> 14 <block wx:else>
15 <slot 15 <slot
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
19 <slot wx:else name="icon" /> 19 <slot wx:else name="icon" />
20 </block> 20 </block>
21 <van-info 21 <van-info
22 wx:if="{{ info !== null }}" 22 dot="{{ dot }}"
23 info="{{ info }}" 23 info="{{ info }}"
24 custom-style="margin-top: 2px" 24 custom-class="van-tabbar-item__info"
25 /> 25 />
26 </view> 26 </view>
27 <view class="van-tabbar-item__text"> 27 <view class="van-tabbar-item__text">
......
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{color:#7d7e80;height:100%;display:-webkit-flex;display:flex;line-height:1;font-size:12px;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-tabbar-item__icon{font-size:18px;margin-bottom:5px;position:relative}.van-tabbar-item__icon--dot:after{top:0;right:-8px;width:8px;height:8px;content:" ";position:absolute;border-radius:100%;background-color:#f44}.van-tabbar-item__icon image{width:30px;height:18px;display:block}.van-tabbar-item--active{color:#1989fa}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;height:100%;color:#7d7e80;color:var(--tabbar-item-text-color,#7d7e80);font-size:12px;font-size:var(--tabbar-item-font-size,12px);line-height:1;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{position:relative;margin-bottom:5px;margin-bottom:var(--tabbar-item-margin-bottom,5px);font-size:18px;font-size:var(--tabbar-item-icon-size,18px)}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:#1989fa;color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({ 2 VantComponent({
4 mixins: [safeArea()],
5 relation: { 3 relation: {
6 name: 'tabbar-item', 4 name: 'tabbar-item',
7 type: 'descendant', 5 type: 'descendant',
8 linked(target) { 6 linked(target) {
9 this.children = this.children || [];
10 this.children.push(target); 7 this.children.push(target);
11 this.setActiveItem(); 8 target.parent = this;
9 target.updateFromParent();
12 }, 10 },
13 unlinked(target) { 11 unlinked(target) {
14 this.children = this.children || []; 12 this.children = this.children.filter((item) => item !== target);
15 this.children = this.children.filter(item => item !== target); 13 this.updateChildren();
16 this.setActiveItem();
17 } 14 }
18 }, 15 },
19 props: { 16 props: {
20 active: Number, 17 active: {
21 activeColor: String, 18 type: null,
19 observer: 'updateChildren'
20 },
21 activeColor: {
22 type: String,
23 observer: 'updateChildren'
24 },
25 inactiveColor: {
26 type: String,
27 observer: 'updateChildren'
28 },
22 fixed: { 29 fixed: {
23 type: Boolean, 30 type: Boolean,
24 value: true 31 value: true
25 }, 32 },
33 border: {
34 type: Boolean,
35 value: true
36 },
26 zIndex: { 37 zIndex: {
27 type: Number, 38 type: Number,
28 value: 1 39 value: 1
40 },
41 safeAreaInsetBottom: {
42 type: Boolean,
43 value: true
29 } 44 }
30 }, 45 },
31 watch: { 46 beforeCreate() {
32 active(active) { 47 this.children = [];
33 this.currentActive = active;
34 this.setActiveItem();
35 }
36 },
37 created() {
38 this.currentActive = this.data.active;
39 }, 48 },
40 methods: { 49 methods: {
41 setActiveItem() { 50 updateChildren() {
42 if (!Array.isArray(this.children) || !this.children.length) { 51 const { children } = this;
52 if (!Array.isArray(children) || !children.length) {
43 return Promise.resolve(); 53 return Promise.resolve();
44 } 54 }
45 return Promise.all(this.children.map((item, index) => item.setActive({ 55 return Promise.all(children.map((child) => child.updateFromParent()));
46 active: index === this.currentActive,
47 color: this.data.activeColor
48 })));
49 }, 56 },
50 onChange(child) { 57 onChange(child) {
51 const active = (this.children || []).indexOf(child); 58 const index = this.children.indexOf(child);
52 if (active !== this.currentActive && active !== -1) { 59 const active = child.data.name || index;
53 this.currentActive = active; 60 if (active !== this.data.active) {
54 this.setActiveItem().then(() => { 61 this.$emit('change', active);
55 this.$emit('change', active);
56 });
57 } 62 }
58 } 63 }
59 } 64 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <view 3 <view
4 class="custom-class van-hairline--top-bottom {{ utils.bem('tabbar', { fixed, safe: isIPhoneX && safeAreaInsetBottom }) }}" 4 class="custom-class {{ border ? 'van-hairline--top-bottom' : '' }} {{ utils.bem('tabbar', { fixed, safe: safeAreaInsetBottom }) }}"
5 style="{{ zIndex ? 'z-index: ' + zIndex : '' }}" 5 style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
6 > 6 >
7 <slot /> 7 <slot />
......
1 @import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;background-color:#fff}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:34px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;height:var(--tabbar-height,50px);background-color:#fff;background-color:var(--tabbar-background-color,#fff)}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch'; 2 import { touch } from '../mixins/touch';
3 import { isDef, addUnit } from '../common/utils';
3 VantComponent({ 4 VantComponent({
4 mixins: [touch], 5 mixins: [touch],
5 classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'], 6 classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
6 relation: { 7 relation: {
7 name: 'tab', 8 name: 'tab',
8 type: 'descendant', 9 type: 'descendant',
9 linked(child) { 10 linked(target) {
10 this.child.push(child); 11 target.index = this.children.length;
11 this.updateTabs(this.data.tabs.concat(child.data)); 12 this.children.push(target);
13 this.updateTabs();
12 }, 14 },
13 unlinked(child) { 15 unlinked(target) {
14 const index = this.child.indexOf(child); 16 this.children = this.children
15 const { tabs } = this.data; 17 .filter((child) => child !== target)
16 tabs.splice(index, 1); 18 .map((child, index) => {
17 this.child.splice(index, 1); 19 child.index = index;
18 this.updateTabs(tabs); 20 return child;
21 });
22 this.updateTabs();
19 } 23 }
20 }, 24 },
21 props: { 25 props: {
22 color: String, 26 color: {
27 type: String,
28 observer: 'setLine'
29 },
23 sticky: Boolean, 30 sticky: Boolean,
24 animated: Boolean, 31 animated: {
32 type: Boolean,
33 observer: 'setTrack'
34 },
25 swipeable: Boolean, 35 swipeable: Boolean,
26 lineWidth: { 36 lineWidth: {
27 type: Number, 37 type: [String, Number],
28 value: -1 38 value: -1,
39 observer: 'setLine'
29 }, 40 },
30 lineHeight: { 41 lineHeight: {
31 type: Number, 42 type: [String, Number],
32 value: -1 43 value: -1,
44 observer: 'setLine'
33 }, 45 },
46 titleActiveColor: String,
47 titleInactiveColor: String,
34 active: { 48 active: {
35 type: Number, 49 type: [String, Number],
36 value: 0 50 value: 0,
51 observer(name) {
52 if (name !== this.getCurrentName()) {
53 this.setCurrentIndexByName(name);
54 }
55 }
37 }, 56 },
38 type: { 57 type: {
39 type: String, 58 type: String,
...@@ -43,6 +62,10 @@ VantComponent({ ...@@ -43,6 +62,10 @@ VantComponent({
43 type: Boolean, 62 type: Boolean,
44 value: true 63 value: true
45 }, 64 },
65 ellipsis: {
66 type: Boolean,
67 value: true
68 },
46 duration: { 69 duration: {
47 type: Number, 70 type: Number,
48 value: 0.3 71 value: 0.3
...@@ -53,12 +76,21 @@ VantComponent({ ...@@ -53,12 +76,21 @@ VantComponent({
53 }, 76 },
54 swipeThreshold: { 77 swipeThreshold: {
55 type: Number, 78 type: Number,
56 value: 4 79 value: 4,
80 observer(value) {
81 this.setData({
82 scrollable: this.children.length > value || !this.data.ellipsis
83 });
84 }
57 }, 85 },
58 offsetTop: { 86 offsetTop: {
59 type: Number, 87 type: Number,
60 value: 0 88 value: 0
61 } 89 },
90 lazyRender: {
91 type: Boolean,
92 value: true
93 },
62 }, 94 },
63 data: { 95 data: {
64 tabs: [], 96 tabs: [],
...@@ -66,89 +98,114 @@ VantComponent({ ...@@ -66,89 +98,114 @@ VantComponent({
66 scrollLeft: 0, 98 scrollLeft: 0,
67 scrollable: false, 99 scrollable: false,
68 trackStyle: '', 100 trackStyle: '',
69 wrapStyle: '', 101 currentIndex: null,
70 position: '' 102 container: null
71 },
72 watch: {
73 swipeThreshold() {
74 this.set({
75 scrollable: this.child.length > this.data.swipeThreshold
76 });
77 },
78 color: 'setLine',
79 lineWidth: 'setLine',
80 lineHeight: 'setLine',
81 active: 'setActiveTab',
82 animated: 'setTrack',
83 offsetTop: 'setWrapStyle'
84 }, 103 },
85 beforeCreate() { 104 beforeCreate() {
86 this.child = []; 105 this.children = [];
87 }, 106 },
88 mounted() { 107 mounted() {
108 this.setData({
109 container: () => this.createSelectorQuery().select('.van-tabs')
110 });
89 this.setLine(true); 111 this.setLine(true);
90 this.setTrack(); 112 this.setTrack();
91 this.scrollIntoView(); 113 this.scrollIntoView();
92 this.getRect('.van-tabs__wrap').then((rect) => {
93 this.navHeight = rect.height;
94 this.observerContentScroll();
95 });
96 },
97 destroyed() {
98 this.createIntersectionObserver().disconnect();
99 }, 114 },
100 methods: { 115 methods: {
101 updateTabs(tabs) { 116 updateTabs() {
102 tabs = tabs || this.data.tabs; 117 const { children = [], data } = this;
103 this.set({ 118 this.setData({
104 tabs, 119 tabs: children.map((child) => child.data),
105 scrollable: tabs.length > this.data.swipeThreshold 120 scrollable: this.children.length > data.swipeThreshold || !data.ellipsis
106 }); 121 });
107 this.setActiveTab(); 122 this.setCurrentIndexByName(this.getCurrentName() || data.active);
108 }, 123 },
109 trigger(eventName, index) { 124 trigger(eventName) {
125 const { currentIndex } = this.data;
126 const child = this.children[currentIndex];
110 this.$emit(eventName, { 127 this.$emit(eventName, {
111 index, 128 index: currentIndex,
112 title: this.data.tabs[index].title 129 name: child.getComputedName(),
130 title: child.data.title
113 }); 131 });
114 }, 132 },
115 onTap(event) { 133 onTap(event) {
116 const { index } = event.currentTarget.dataset; 134 const { index } = event.currentTarget.dataset;
117 if (this.data.tabs[index].disabled) { 135 const child = this.children[index];
118 this.trigger('disabled', index); 136 if (child.data.disabled) {
137 this.trigger('disabled');
119 } 138 }
120 else { 139 else {
121 this.trigger('click', index); 140 this.setCurrentIndex(index);
122 this.setActive(index); 141 wx.nextTick(() => {
142 this.trigger('click');
143 });
144 }
145 },
146 // correct the index of active tab
147 setCurrentIndexByName(name) {
148 const { children = [] } = this;
149 const matched = children.filter((child) => child.getComputedName() === name);
150 const defaultIndex = (children[0] || {}).index || 0;
151 this.setCurrentIndex(matched.length ? matched[0].index : defaultIndex);
152 },
153 setCurrentIndex(currentIndex) {
154 const { data, children = [] } = this;
155 if (!isDef(currentIndex) ||
156 currentIndex >= children.length ||
157 currentIndex < 0) {
158 return;
123 } 159 }
160 const shouldEmitChange = data.currentIndex !== null;
161 this.setData({ currentIndex });
162 children.forEach((item, index) => {
163 const active = index === currentIndex;
164 if (active !== item.data.active || !item.inited) {
165 item.updateRender(active, this);
166 }
167 });
168 wx.nextTick(() => {
169 this.setLine();
170 this.setTrack();
171 this.scrollIntoView();
172 this.trigger('input');
173 if (shouldEmitChange) {
174 this.trigger('change');
175 }
176 });
124 }, 177 },
125 setActive(active) { 178 getCurrentName() {
126 if (active !== this.data.active) { 179 const activeTab = this.children[this.data.currentIndex];
127 this.trigger('change', active); 180 if (activeTab) {
128 this.set({ active }); 181 return activeTab.getComputedName();
129 this.setActiveTab();
130 } 182 }
131 }, 183 },
132 setLine(skipTransition) { 184 setLine(skipTransition) {
133 if (this.data.type !== 'line') { 185 if (this.data.type !== 'line') {
134 return; 186 return;
135 } 187 }
136 const { color, active, duration, lineWidth, lineHeight } = this.data; 188 const { color, duration, currentIndex, lineWidth, lineHeight } = this.data;
137 this.getRect('.van-tab', true).then((rects) => { 189 this.getRect('.van-tab', true).then((rects = []) => {
138 const rect = rects[active]; 190 const rect = rects[currentIndex];
191 if (rect == null) {
192 return;
193 }
139 const width = lineWidth !== -1 ? lineWidth : rect.width / 2; 194 const width = lineWidth !== -1 ? lineWidth : rect.width / 2;
140 const height = lineHeight !== -1 ? `height: ${lineHeight}px;` : ''; 195 const height = lineHeight !== -1
196 ? `height: ${addUnit(lineHeight)}; border-radius: ${addUnit(lineHeight)};`
197 : '';
141 let left = rects 198 let left = rects
142 .slice(0, active) 199 .slice(0, currentIndex)
143 .reduce((prev, curr) => prev + curr.width, 0); 200 .reduce((prev, curr) => prev + curr.width, 0);
144 left += (rect.width - width) / 2; 201 left += (rect.width - width) / 2;
145 const transition = skipTransition 202 const transition = skipTransition
146 ? '' 203 ? ''
147 : `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`; 204 : `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`;
148 this.set({ 205 this.setData({
149 lineStyle: ` 206 lineStyle: `
150 ${height} 207 ${height}
151 width: ${width}px; 208 width: ${addUnit(width)};
152 background-color: ${color}; 209 background-color: ${color};
153 -webkit-transform: translateX(${left}px); 210 -webkit-transform: translateX(${left}px);
154 transform: translateX(${left}px); 211 transform: translateX(${left}px);
...@@ -158,47 +215,18 @@ VantComponent({ ...@@ -158,47 +215,18 @@ VantComponent({
158 }); 215 });
159 }, 216 },
160 setTrack() { 217 setTrack() {
161 const { animated, active, duration } = this.data; 218 const { animated, duration, currentIndex } = this.data;
162 if (!animated) 219 this.setData({
163 return ''; 220 trackStyle: `
164 this.getRect('.van-tabs__content').then((rect) => { 221 transform: translate3d(${-100 * currentIndex}%, 0, 0);
165 const { width } = rect; 222 -webkit-transition-duration: ${animated ? duration : 0}s;
166 this.set({ 223 transition-duration: ${animated ? duration : 0}s;
167 trackStyle: ` 224 `
168 width: ${width * this.child.length}px;
169 left: ${-1 * active * width}px;
170 transition: left ${duration}s;
171 display: -webkit-box;
172 display: flex;
173 `
174 });
175 const props = { width, animated };
176 this.child.forEach((item) => {
177 item.set(props);
178 });
179 });
180 },
181 setActiveTab() {
182 this.child.forEach((item, index) => {
183 const data = {
184 active: index === this.data.active
185 };
186 if (data.active) {
187 data.inited = true;
188 }
189 if (data.active !== item.data.active) {
190 item.set(data);
191 }
192 });
193 this.set({}, () => {
194 this.setLine();
195 this.setTrack();
196 this.scrollIntoView();
197 }); 225 });
198 }, 226 },
199 // scroll active tab into view 227 // scroll active tab into view
200 scrollIntoView() { 228 scrollIntoView() {
201 const { active, scrollable } = this.data; 229 const { currentIndex, scrollable } = this.data;
202 if (!scrollable) { 230 if (!scrollable) {
203 return; 231 return;
204 } 232 }
...@@ -206,15 +234,18 @@ VantComponent({ ...@@ -206,15 +234,18 @@ VantComponent({
206 this.getRect('.van-tab', true), 234 this.getRect('.van-tab', true),
207 this.getRect('.van-tabs__nav') 235 this.getRect('.van-tabs__nav')
208 ]).then(([tabRects, navRect]) => { 236 ]).then(([tabRects, navRect]) => {
209 const tabRect = tabRects[active]; 237 const tabRect = tabRects[currentIndex];
210 const offsetLeft = tabRects 238 const offsetLeft = tabRects
211 .slice(0, active) 239 .slice(0, currentIndex)
212 .reduce((prev, curr) => prev + curr.width, 0); 240 .reduce((prev, curr) => prev + curr.width, 0);
213 this.set({ 241 this.setData({
214 scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2 242 scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2
215 }); 243 });
216 }); 244 });
217 }, 245 },
246 onTouchScroll(event) {
247 this.$emit('scroll', event.detail);
248 },
218 onTouchStart(event) { 249 onTouchStart(event) {
219 if (!this.data.swipeable) 250 if (!this.data.swipeable)
220 return; 251 return;
...@@ -229,84 +260,17 @@ VantComponent({ ...@@ -229,84 +260,17 @@ VantComponent({
229 onTouchEnd() { 260 onTouchEnd() {
230 if (!this.data.swipeable) 261 if (!this.data.swipeable)
231 return; 262 return;
232 const { active, tabs } = this.data; 263 const { tabs, currentIndex } = this.data;
233 const { direction, deltaX, offsetX } = this; 264 const { direction, deltaX, offsetX } = this;
234 const minSwipeDistance = 50; 265 const minSwipeDistance = 50;
235 if (direction === 'horizontal' && offsetX >= minSwipeDistance) { 266 if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
236 if (deltaX > 0 && active !== 0) { 267 if (deltaX > 0 && currentIndex !== 0) {
237 this.setActive(active - 1); 268 this.setCurrentIndex(currentIndex - 1);
238 } 269 }
239 else if (deltaX < 0 && active !== tabs.length - 1) { 270 else if (deltaX < 0 && currentIndex !== tabs.length - 1) {
240 this.setActive(active + 1); 271 this.setCurrentIndex(currentIndex + 1);
241 } 272 }
242 } 273 }
243 },
244 setWrapStyle() {
245 const { offsetTop, position } = this.data;
246 let wrapStyle;
247 switch (position) {
248 case 'top':
249 wrapStyle = `
250 top: ${offsetTop}px;
251 position: fixed;
252 `;
253 break;
254 case 'bottom':
255 wrapStyle = `
256 top: auto;
257 bottom: 0;
258 `;
259 break;
260 default:
261 wrapStyle = '';
262 }
263 // cut down `set`
264 if (wrapStyle === this.data.wrapStyle)
265 return;
266 this.set({ wrapStyle });
267 },
268 observerContentScroll() {
269 if (!this.data.sticky) {
270 return;
271 }
272 const { offsetTop } = this.data;
273 const { windowHeight } = wx.getSystemInfoSync();
274 this.createIntersectionObserver().disconnect();
275 this.createIntersectionObserver()
276 .relativeToViewport({ top: -(this.navHeight + offsetTop) })
277 .observe('.van-tabs', (res) => {
278 const { top } = res.boundingClientRect;
279 if (top > offsetTop) {
280 return;
281 }
282 const position = res.intersectionRatio > 0 ? 'top' : 'bottom';
283 this.$emit('scroll', {
284 scrollTop: top + offsetTop,
285 isFixed: position === 'top'
286 });
287 this.setPosition(position);
288 });
289 this.createIntersectionObserver()
290 .relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
291 .observe('.van-tabs', (res) => {
292 const { top, bottom } = res.boundingClientRect;
293 if (bottom < this.navHeight) {
294 return;
295 }
296 const position = res.intersectionRatio > 0 ? 'top' : '';
297 this.$emit('scroll', {
298 scrollTop: top + offsetTop,
299 isFixed: position === 'top'
300 });
301 this.setPosition(position);
302 });
303 },
304 setPosition(position) {
305 if (position !== this.data.position) {
306 this.set({ position }).then(() => {
307 this.setWrapStyle();
308 });
309 }
310 } 274 }
311 } 275 }
312 }); 276 });
......
1 { 1 {
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-info": "../info/index" 4 "van-info": "../info/index",
5 "van-sticky": "../sticky/index"
5 } 6 }
6 } 7 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 <wxs src="./index.wxs" module="getters" />
2 3
3 <view class="custom-class {{ utils.bem('tabs', [type]) }}"> 4 <view class="custom-class {{ utils.bem('tabs', [type]) }}">
4 <view style="z-index: {{ zIndex }}; {{ wrapStyle }}" class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}"> 5 <van-sticky
5 <slot name="nav-left" /> 6 disabled="{{ !sticky }}"
7 z-index="{{ zIndex }}"
8 offset-top="{{ offsetTop }}"
9 container="{{ container }}"
10 bind:scroll="onTouchScroll"
11 >
12 <view class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
13 <slot name="nav-left" />
6 14
7 <scroll-view 15 <scroll-view
8 scroll-x="{{ scrollable }}" 16 scroll-x="{{ scrollable }}"
9 scroll-with-animation 17 scroll-with-animation
10 scroll-left="{{ scrollLeft }}" 18 scroll-left="{{ scrollLeft }}"
11 class="van-tabs__scroll--{{ type }}" 19 class="{{ utils.bem('tabs__scroll', [type]) }}"
12 style="{{ color ? 'border-color: ' + color : '' }}" 20 style="{{ color ? 'border-color: ' + color : '' }}"
13 > 21 >
14 <view class="{{ utils.bem('tabs__nav', [type]) }} nav-class"> 22 <view class="{{ utils.bem('tabs__nav', [type]) }} nav-class">
15 <view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" /> 23 <view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" />
16 <view 24 <view
17 wx:for="{{ tabs }}" 25 wx:for="{{ tabs }}"
18 wx:key="index" 26 wx:key="index"
19 data-index="{{ index }}" 27 data-index="{{ index }}"
20 class="van-ellipsis tab-class {{ index === active ? 'tab-active-class' : '' }} {{ utils.bem('tab', { active: index === active, disabled: item.disabled }) }}" 28 class="{{ getters.tabClass(index === currentIndex, ellipsis) }} {{ utils.bem('tab', { active: index === currentIndex, disabled: item.disabled, complete: !ellipsis }) }}"
21 style="{{ color && index !== active && type === 'card' && !item.disabled ? 'color: ' + color : '' }} {{ color && index === active && type === 'card' ? ';background-color:' + color : '' }} {{ color ? ';border-color: ' + color : '' }} {{ scrollable ? ';flex-basis:' + (88 / swipeThreshold) + '%' : '' }}" 29 style="{{ getters.tabStyle(index === currentIndex, ellipsis, color, type, item.disabled, titleActiveColor, titleInactiveColor, swipeThreshold, scrollable) }}"
22 bind:tap="onTap" 30 bind:tap="onTap"
23 > 31 >
24 <view class="van-ellipsis {{ utils.bem('tab__title', { dot: item.dot }) }}" style="{{ item.titleStyle }}"> 32 <view class="{{ ellipsis ? 'van-ellipsis' : '' }}" style="{{ item.titleStyle }}">
25 {{ item.title }} 33 {{ item.title }}
26 <van-info 34 <van-info
27 wx:if="{{ item.info !== null }}" 35 wx:if="{{ item.info !== null || item.dot }}"
28 info="{{ item.info }}" 36 info="{{ item.info }}"
29 custom-class="van-tab__title__info" 37 dot="{{ item.dot }}"
30 /> 38 custom-class="van-tab__title__info"
39 />
40 </view>
31 </view> 41 </view>
32 </view> 42 </view>
33 </view> 43 </scroll-view>
34 </scroll-view> 44
45 <slot name="nav-right" />
46 </view>
47 </van-sticky>
35 48
36 <slot name="nav-right" />
37 </view>
38 <view 49 <view
39 class="van-tabs__content" 50 class="van-tabs__content"
40 bind:touchstart="onTouchStart" 51 bind:touchstart="onTouchStart"
......
1 /* eslint-disable */
2 function tabClass(active, ellipsis) {
3 var classes = ['tab-class'];
4
5 if (active) {
6 classes.push('tab-active-class');
7 }
8
9 if (ellipsis) {
10 classes.push('van-ellipsis');
11 }
12
13 return classes.join(' ');
14 }
15
16 function tabStyle(
17 active,
18 ellipsis,
19 color,
20 type,
21 disabled,
22 activeColor,
23 inactiveColor,
24 swipeThreshold,
25 scrollable
26 ) {
27 var styles = [];
28 var isCard = type === 'card';
29 // card theme color
30 if (color && isCard) {
31 styles.push('border-color:' + color);
32
33 if (!disabled) {
34 if (active) {
35 styles.push('background-color:' + color);
36 } else {
37 styles.push('color:' + color);
38 }
39 }
40 }
41
42 var titleColor = active ? activeColor : inactiveColor;
43 if (titleColor) {
44 styles.push('color:' + titleColor);
45 }
46
47 if (scrollable && ellipsis) {
48 styles.push('flex-basis:' + 88 / swipeThreshold + '%');
49 }
50
51 return styles.join(';');
52 }
53
54 module.exports.tabClass = tabClass;
55 module.exports.tabStyle = tabStyle;
1 @import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{position:absolute;top:0;right:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-tabs__wrap--page-top{position:fixed}.van-tabs__wrap--content-bottom{top:auto;bottom:0}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll--card{border:1px solid #f44;border-radius:2px}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--line{height:100%}.van-tabs__nav--card{height:30px}.van-tabs__nav--card .van-tab{line-height:30px;color:#f44;border-right:1px solid #f44}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;background-color:#f44}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;background-color:#f44;border-radius:3px}.van-tabs--line{padding-top:44px}.van-tabs--line .van-tabs__wrap{height:44px}.van-tabs--card{padding-top:30px;margin:0 15px}.van-tabs--card .van-tabs__wrap{height:30px}.van-tabs__content{overflow:hidden}.van-tab,.van-tabs__track{position:relative}.van-tab{min-width:0;padding:0 5px;font-size:14px;line-height:44px;color:#7d7e80;text-align:center;cursor:pointer;box-sizing:border-box;-webkit-flex:1;flex:1}.van-tab--active{font-weight:500;color:#333}.van-tab--disabled{color:#c9c9c9}.van-tab__title--dot:after{display:inline-block;width:8px;height:8px;vertical-align:middle;background-color:#f44;border-radius:100%;content:""}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{display:-webkit-flex;display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll{background-color:#fff;background-color:var(--tabs-nav-background-color,#fff)}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{margin:0 16px;margin:0 var(--padding-md,16px)}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:30px;height:var(--tabs-card-height,30px);border:1px solid #ee0a24;border:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24);border-radius:2px;border-radius:var(--border-radius-sm,2px)}.van-tabs__nav--card .van-tab{color:#ee0a24;color:var(--tabs-default-color,#ee0a24);line-height:28px;line-height:calc(var(--tabs-card-height, 30px) - 2*var(--border-width-base, 1px));border-right:1px solid #ee0a24;border-right:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;color:var(--white,#fff);background-color:#ee0a24;background-color:var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;height:var(--tabs-bottom-bar-height,3px);border-radius:3px;border-radius:var(--tabs-bottom-bar-height,3px);background-color:#ee0a24;background-color:var(--tabs-bottom-bar-color,#ee0a24)}.van-tabs__track{position:relative;display:-webkit-flex;display:flex;width:100%;height:100%;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-tabs__content{overflow:hidden}.van-tabs--line .van-tabs__wrap{height:44px;height:var(--tabs-line-height,44px)}.van-tabs--card .van-tabs__wrap{height:30px;height:var(--tabs-card-height,30px)}.van-tab{position:relative;-webkit-flex:1;flex:1;box-sizing:border-box;min-width:0;padding:0 5px;text-align:center;cursor:pointer;color:#7d7e80;color:var(--tab-text-color,#7d7e80);font-size:14px;font-size:var(--tab-font-size,14px);line-height:44px;line-height:var(--tabs-line-height,44px)}.van-tab--active{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--tab-active-text-color,#323233)}.van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab--complete{-webkit-flex:1 0 auto!important;flex:1 0 auto!important}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 import { RED, BLUE, GREEN } from '../common/color';
3 const DEFAULT_COLOR = '#999';
4 const COLOR_MAP = {
5 danger: RED,
6 primary: BLUE,
7 success: GREEN
8 };
9 VantComponent({ 2 VantComponent({
10 props: { 3 props: {
11 size: String, 4 size: String,
12 type: String,
13 mark: Boolean, 5 mark: Boolean,
14 color: String, 6 color: String,
15 plain: Boolean, 7 plain: Boolean,
16 round: Boolean, 8 round: Boolean,
17 textColor: String 9 textColor: String,
10 type: {
11 type: String,
12 value: 'default'
13 },
14 closeable: Boolean
18 }, 15 },
19 computed: { 16 methods: {
20 style() { 17 onClose() {
21 const color = this.data.color || COLOR_MAP[this.data.type] || DEFAULT_COLOR; 18 this.$emit('close');
22 const key = this.data.plain ? 'color' : 'background-color';
23 const style = { [key]: color };
24 if (this.data.textColor) {
25 style.color = this.data.textColor;
26 }
27 return Object.keys(style).map(key => `${key}: ${style[key]}`).join(';');
28 } 19 }
29 } 20 }
30 }); 21 });
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 2
3 <view 3 <view
4 class="custom-class {{ utils.bem('tag', [size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}" 4 class="custom-class {{ utils.bem('tag', [type, size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
5 style="{{ style }}" 5 style="{{ color && !plain ? 'background-color: ' + color + ';' : '' }}{{ textColor || (color && plain) ? 'color: ' + (textColor || color) : '' }}"
6 > 6 >
7 <slot /> 7 <slot />
8 <van-icon
9 wx:if="{{ closeable }}"
10 name="cross"
11 custom-class="van-tag__close"
12 bind:click="onClose"
13 />
8 </view> 14 </view>
......
1 @import '../common/index.wxss';.van-tag{color:#fff;font-size:10px;padding:.2em .5em;line-height:normal;border-radius:.2em;display:inline-block}.van-tag:after{border-color:currentColor;border-radius:.4em}.van-tag--mark{padding-right:.6em;border-radius:0 .8em .8em 0}.van-tag--mark:after{border-radius:0 1.6em 1.6em 0}.van-tag--round{border-radius:.8em}.van-tag--round:after{border-radius:1.6em}.van-tag--medium{font-size:12px}.van-tag--large{font-size:14px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-tag{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;line-height:normal;padding:.2em .5em;padding:var(--tag-padding,.2em .5em);color:#fff;color:var(--tag-text-color,#fff);font-size:10px;font-size:var(--tag-font-size,10px);border-radius:.2em;border-radius:var(--tag-border-radius,.2em)}.van-tag:after{border-color:currentColor;border-radius:.2em * 2;border-radius:var(--tag-border-radius,.2em) * 2}.van-tag--default{background-color:#969799;background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:#969799;color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:#ee0a24;background-color:var(--tag-dander-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:#ee0a24;color:var(--tag-dander-color,#ee0a24)}.van-tag--primary{background-color:#1989fa;background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:#1989fa;color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:#07c160;background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:#07c160;color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:#ff976a;background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:#ff976a;color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:#fff;background-color:var(--tag-plain-background-color,#fff)}.van-tag--mark{padding-right:.7em}.van-tag--mark,.van-tag--mark:after{border-radius:0 999px 999px 0;border-radius:0 var(--tag-round-border-radius,999px) var(--tag-round-border-radius,999px) 0}.van-tag--round,.van-tag--round:after{border-radius:999px;border-radius:var(--tag-round-border-radius,999px)}.van-tag--medium{font-size:12px;font-size:var(--tag-medium-font-size,12px)}.van-tag--large{font-size:14px;font-size:var(--tag-large-font-size,14px)}.van-tag__close{margin-left:2px}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -23,11 +23,6 @@ VantComponent({ ...@@ -23,11 +23,6 @@ VantComponent({
23 } 23 }
24 }, 24 },
25 methods: { 25 methods: {
26 clear() {
27 this.set({
28 show: false
29 });
30 },
31 // for prevent touchmove 26 // for prevent touchmove
32 noop() { } 27 noop() { }
33 } 28 }
......
1 <van-overlay 1 <van-overlay
2 wx:if="{{ mask || forbidClick }}" 2 wx:if="{{ mask || forbidClick }}"
3 show="{{ show }}" 3 show="{{ show }}"
4 mask="{{ mask }}"
5 z-index="{{ zIndex }}" 4 z-index="{{ zIndex }}"
5 custom-style="{{ mask ? '' : 'background-color: transparent;' }}"
6 /> 6 />
7 <van-transition 7 <van-transition
8 show="{{ show }}" 8 show="{{ show }}"
...@@ -27,5 +27,7 @@ ...@@ -27,5 +27,7 @@
27 <van-icon wx:else class="van-toast__icon" name="{{ type }}" /> 27 <van-icon wx:else class="van-toast__icon" name="{{ type }}" />
28 <text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text> 28 <text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text>
29 </block> 29 </block>
30
31 <slot />
30 </view> 32 </view>
31 </van-transition> 33 </van-transition>
......
1 @import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;color:#fff;font-size:14px;line-height:20px;border-radius:4px;word-break:break-all;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;box-sizing:initial;background-color:rgba(51,51,51,.88);white-space:pre-wrap}.van-toast__container{position:fixed;top:50%;left:50%;max-width:70%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-toast--text{padding:8px 12px;min-width:96px}.van-toast--icon{width:90px;padding:15px;min-height:90px}.van-toast--icon .van-toast__icon{font-size:48px}.van-toast--icon .van-toast__text{padding-top:5px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:initial;color:#fff;color:var(--toast-text-color,#fff);font-size:14px;font-size:var(--toast-font-size,14px);line-height:20px;line-height:var(--toast-line-height,20px);white-space:pre-wrap;word-wrap:break-word;background-color:rgba(50,50,51,.88);background-color:var(--toast-background-color,rgba(50,50,51,.88));border-radius:4px;border-radius:var(--toast-border-radius,4px)}.van-toast__container{position:fixed;top:50%;left:50%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);max-width:70%;max-width:var(--toast-max-width,70%)}.van-toast--text{min-width:96px;min-width:var(--toast-text-min-width,96px);padding:8px 12px;padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{width:90px;width:var(--toast-default-width,90px);min-height:90px;min-height:var(--toast-default-min-height,90px);padding:16px;padding:var(--toast-default-padding,16px)}.van-toast--icon .van-toast__icon{font-size:48px;font-size:var(--toast-icon-size,48px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
...\ No newline at end of file ...\ No newline at end of file
......
1 /// <reference types="miniprogram-api-typings" />
1 declare type ToastMessage = string | number; 2 declare type ToastMessage = string | number;
2 export declare type ToastOptions = { 3 interface ToastOptions {
3 show?: boolean; 4 show?: boolean;
4 type?: string; 5 type?: string;
5 mask?: boolean; 6 mask?: boolean;
6 zIndex?: number; 7 zIndex?: number;
7 context?: any; 8 context?: WechatMiniprogram.Component.TrivialInstance | WechatMiniprogram.Page.TrivialInstance;
8 position?: string; 9 position?: string;
9 duration?: number; 10 duration?: number;
10 selector?: string; 11 selector?: string;
11 forbidClick?: boolean; 12 forbidClick?: boolean;
12 loadingType?: string; 13 loadingType?: string;
13 message?: ToastMessage; 14 message?: ToastMessage;
14 }; 15 onClose?: () => void;
15 export interface Toast { 16 }
16 (message: ToastOptions | ToastMessage, options?: ToastOptions): Weapp.Component; 17 declare function Toast(toastOptions: ToastOptions | ToastMessage): WechatMiniprogram.Component.TrivialInstance;
17 loading?(options?: ToastOptions | ToastMessage): Weapp.Component; 18 declare namespace Toast {
18 success?(options?: ToastOptions | ToastMessage): Weapp.Component; 19 var loading: (options: string | number | ToastOptions) => WechatMiniprogram.Component.Instance<Record<string, any>, Record<string, any>, Record<string, any>>;
19 fail?(options?: ToastOptions | ToastMessage): Weapp.Component; 20 var success: (options: string | number | ToastOptions) => WechatMiniprogram.Component.Instance<Record<string, any>, Record<string, any>, Record<string, any>>;
20 clear?(): void; 21 var fail: (options: string | number | ToastOptions) => WechatMiniprogram.Component.Instance<Record<string, any>, Record<string, any>, Record<string, any>>;
21 setDefaultOptions?(options: ToastOptions): void; 22 var clear: () => void;
22 resetDefaultOptions?(): void; 23 var setDefaultOptions: (options: ToastOptions) => void;
24 var resetDefaultOptions: () => void;
23 } 25 }
24 declare const Toast: Toast;
25 export default Toast; 26 export default Toast;
......
...@@ -5,7 +5,7 @@ const defaultOptions = { ...@@ -5,7 +5,7 @@ const defaultOptions = {
5 message: '', 5 message: '',
6 show: true, 6 show: true,
7 zIndex: 1000, 7 zIndex: 1000,
8 duration: 3000, 8 duration: 2000,
9 position: 'middle', 9 position: 'middle',
10 forbidClick: false, 10 forbidClick: false,
11 loadingType: 'circular', 11 loadingType: 'circular',
...@@ -20,8 +20,8 @@ function getContext() { ...@@ -20,8 +20,8 @@ function getContext() {
20 const pages = getCurrentPages(); 20 const pages = getCurrentPages();
21 return pages[pages.length - 1]; 21 return pages[pages.length - 1];
22 } 22 }
23 const Toast = (options = {}) => { 23 function Toast(toastOptions) {
24 options = Object.assign({}, currentOptions, parseOptions(options)); 24 const options = Object.assign(Object.assign({}, currentOptions), parseOptions(toastOptions));
25 const context = options.context || getContext(); 25 const context = options.context || getContext();
26 const toast = context.selectComponent(options.selector); 26 const toast = context.selectComponent(options.selector);
27 if (!toast) { 27 if (!toast) {
...@@ -30,8 +30,14 @@ const Toast = (options = {}) => { ...@@ -30,8 +30,14 @@ const Toast = (options = {}) => {
30 } 30 }
31 delete options.context; 31 delete options.context;
32 delete options.selector; 32 delete options.selector;
33 toast.clear = () => {
34 toast.setData({ show: false });
35 if (options.onClose) {
36 options.onClose();
37 }
38 };
33 queue.push(toast); 39 queue.push(toast);
34 toast.set(options); 40 toast.setData(options);
35 clearTimeout(toast.timer); 41 clearTimeout(toast.timer);
36 if (options.duration > 0) { 42 if (options.duration > 0) {
37 toast.timer = setTimeout(() => { 43 toast.timer = setTimeout(() => {
...@@ -40,18 +46,18 @@ const Toast = (options = {}) => { ...@@ -40,18 +46,18 @@ const Toast = (options = {}) => {
40 }, options.duration); 46 }, options.duration);
41 } 47 }
42 return toast; 48 return toast;
43 }; 49 }
44 const createMethod = type => options => Toast(Object.assign({ type }, parseOptions(options))); 50 const createMethod = (type) => (options) => Toast(Object.assign({ type }, parseOptions(options)));
45 ['loading', 'success', 'fail'].forEach(method => { 51 Toast.loading = createMethod('loading');
46 Toast[method] = createMethod(method); 52 Toast.success = createMethod('success');
47 }); 53 Toast.fail = createMethod('fail');
48 Toast.clear = () => { 54 Toast.clear = () => {
49 queue.forEach(toast => { 55 queue.forEach(toast => {
50 toast.clear(); 56 toast.clear();
51 }); 57 });
52 queue = []; 58 queue = [];
53 }; 59 };
54 Toast.setDefaultOptions = options => { 60 Toast.setDefaultOptions = (options) => {
55 Object.assign(currentOptions, options); 61 Object.assign(currentOptions, options);
56 }; 62 };
57 Toast.resetDefaultOptions = () => { 63 Toast.resetDefaultOptions = () => {
......
1 @import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);opacity:0}.van-fade-down-enter,.van-fade-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);opacity:0}.van-fade-left-enter,.van-fade-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.van-fade-right-enter,.van-fade-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component'; 1 import { VantComponent } from '../common/component';
2 const ITEM_HEIGHT = 44; 2 import { addUnit } from '../common/utils';
3 VantComponent({ 3 VantComponent({
4 classes: [ 4 classes: [
5 'main-item-class', 5 'main-item-class',
...@@ -10,47 +10,50 @@ VantComponent({ ...@@ -10,47 +10,50 @@ VantComponent({
10 'content-disabled-class' 10 'content-disabled-class'
11 ], 11 ],
12 props: { 12 props: {
13 items: Array, 13 items: {
14 type: Array,
15 observer: 'updateSubItems'
16 },
17 activeId: null,
14 mainActiveIndex: { 18 mainActiveIndex: {
15 type: Number, 19 type: Number,
16 value: 0 20 value: 0,
21 observer: 'updateSubItems'
17 }, 22 },
18 activeId: { 23 height: {
19 type: [Number, String] 24 type: [Number, String],
25 value: 300,
26 observer: 'updateHeight'
20 }, 27 },
21 maxHeight: { 28 max: {
22 type: Number, 29 type: Number,
23 value: 300 30 value: Infinity
24 } 31 }
25 }, 32 },
26 data: { 33 data: {
27 subItems: [], 34 subItems: []
28 mainHeight: 0,
29 itemHeight: 0
30 }, 35 },
31 watch: { 36 created() {
32 items() { 37 this.updateHeight();
33 this.updateSubItems().then(() => {
34 this.updateMainHeight();
35 });
36 },
37 maxHeight() {
38 this.updateItemHeight(this.data.subItems);
39 this.updateMainHeight();
40 },
41 mainActiveIndex: 'updateSubItems'
42 }, 38 },
43 methods: { 39 methods: {
44 // 当一个子项被选择时 40 // 当一个子项被选择时
45 onSelectItem(event) { 41 onSelectItem(event) {
46 const { item } = event.currentTarget.dataset; 42 const { item } = event.currentTarget.dataset;
47 if (!item.disabled) { 43 const isArray = Array.isArray(this.data.activeId);
44 // 判断有没有超出右侧选择的最大数
45 const isOverMax = isArray && this.data.activeId.length >= this.data.max;
46 // 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
47 const isSelected = isArray
48 ? this.data.activeId.indexOf(item.id) > -1
49 : this.data.activeId === item.id;
50 if (!item.disabled && (!isOverMax || isSelected)) {
48 this.$emit('click-item', item); 51 this.$emit('click-item', item);
49 } 52 }
50 }, 53 },
51 // 当一个导航被点击时 54 // 当一个导航被点击时
52 onClickNav(event) { 55 onClickNav(event) {
53 const { index } = event.currentTarget.dataset; 56 const index = event.detail;
54 const item = this.data.items[index]; 57 const item = this.data.items[index];
55 if (!item.disabled) { 58 if (!item.disabled) {
56 this.$emit('click-nav', { index }); 59 this.$emit('click-nav', { index });
...@@ -60,19 +63,12 @@ VantComponent({ ...@@ -60,19 +63,12 @@ VantComponent({
60 updateSubItems() { 63 updateSubItems() {
61 const { items, mainActiveIndex } = this.data; 64 const { items, mainActiveIndex } = this.data;
62 const { children = [] } = items[mainActiveIndex] || {}; 65 const { children = [] } = items[mainActiveIndex] || {};
63 this.updateItemHeight(children);
64 return this.set({ subItems: children }); 66 return this.set({ subItems: children });
65 }, 67 },
66 // 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定 68 updateHeight() {
67 updateMainHeight() { 69 this.setData({
68 const { items = [], subItems = [] } = this.data; 70 innerHeight: addUnit(this.data.height)
69 const maxHeight = Math.max(items.length * ITEM_HEIGHT, subItems.length * ITEM_HEIGHT); 71 });
70 this.set({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
71 },
72 // 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
73 updateItemHeight(subItems) {
74 const itemHeight = Math.min(subItems.length * ITEM_HEIGHT, this.data.maxHeight);
75 return this.set({ itemHeight });
76 } 72 }
77 } 73 }
78 }); 74 });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
2 "component": true, 2 "component": true,
3 "usingComponents": { 3 "usingComponents": {
4 "van-icon": "../icon/index", 4 "van-icon": "../icon/index",
5 "van-cell": "../cell/index" 5 "van-sidebar": "../sidebar/index",
6 "van-sidebar-item": "../sidebar-item/index"
6 } 7 }
7 } 8 }
......
1 <wxs src="../wxs/utils.wxs" module="utils" /> 1 <wxs src="../wxs/utils.wxs" module="utils" />
2 <wxs src="./index.wxs" module="wxs" />
2 3
3 <view 4 <view
4 class="van-tree-select" 5 class="van-tree-select"
5 style="height: {{ mainHeight }}px" 6 style="height: {{ innerHeight }}"
6 > 7 >
7 <scroll-view scroll-y class="van-tree-select__nav"> 8 <scroll-view scroll-y class="van-tree-select__nav">
8 <view 9 <van-sidebar bind:change="onClickNav" custom-class="van-tree-select__nav__inner">
9 wx:for="{{ items }}" 10 <van-sidebar-item
10 wx:key="index" 11 wx:for="{{ items }}"
11 class="van-ellipsis main-item-class {{ utils.bem('tree-select__nitem', { active: mainActiveIndex === index, disabled: item.disabled }) }} {{ mainActiveIndex === index ? 'main-active-class' : '' }} {{ item.disabled ? 'main-disabled-class' : '' }}" 12 wx:key="index"
12 data-index="{{ index }}" 13 custom-class="main-item-class"
13 bind:tap="onClickNav" 14 active-class="main-active-class"
14 > 15 disabled-class="main-disabled-class"
15 {{ item.text }} 16 title="{{ item.text }}"
16 </view> 17 disabled="{{ item.disabled }}"
18 />
19 </van-sidebar>
17 </scroll-view> 20 </scroll-view>
18 <scroll-view 21 <scroll-view scroll-y class="van-tree-select__content">
19 scroll-y 22 <slot name="content" />
20 class="van-tree-select__content"
21 style="height: {{ itemHeight }}px"
22 >
23 <view 23 <view
24 wx:for="{{ subItems }}" 24 wx:for="{{ subItems }}"
25 wx:key="id" 25 wx:key="id"
26 class="van-ellipsis van-hairline--bottom content-item-class {{ utils.bem('tree-select__item', { active: activeId === item.id, disabled: item.disabled }) }} {{ activeId === item.id ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}" 26 class="van-ellipsis content-item-class {{ utils.bem('tree-select__item', { active: wxs.isActive(activeId, item.id), disabled: item.disabled }) }} {{ wxs.isActive(activeId, item.id) ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
27 data-item="{{ item }}" 27 data-item="{{ item }}"
28 bind:tap="onSelectItem" 28 bind:tap="onSelectItem"
29 > 29 >
30 {{ item.text }} 30 {{ item.text }}
31 <van-icon 31 <van-icon
32 wx:if="{{ activeId === item.id }}" 32 wx:if="{{ wxs.isActive(activeId, item.id) }}"
33 name="checked" 33 name="checked"
34 size="16px" 34 size="16px"
35 class="van-tree-select__selected" 35 class="van-tree-select__selected"
......
1 /* eslint-disable */
2 var array = require('../wxs/array.wxs');
3
4 function isActive (activeList, itemId) {
5 if (array.isArray(activeList)) {
6 return activeList.indexOf(itemId) > -1;
7 }
8
9 return activeList === itemId;
10 }
11
12 module.exports.isActive = isActive;
1 @import '../common/index.wxss';.van-tree-select{position:relative;font-size:14px;-webkit-user-select:none;user-select:none}.van-tree-select__nav{position:absolute;top:0;bottom:0;left:0;width:35%;min-width:120px;background-color:#fafafa}.van-tree-select__nitem{position:relative;padding:0 9px 0 15px;line-height:44px}.van-tree-select__nitem--active:after{position:absolute;top:0;bottom:0;left:0;width:3.6px;background-color:#f44;content:""}.van-tree-select__nitem--active{font-weight:700;background-color:#fff}.van-tree-select__nitem--disabled{color:#999}.van-tree-select__content{width:65%;padding-left:15px;margin-left:35%;background-color:#fff;box-sizing:border-box}.van-tree-select__item{position:relative;font-weight:700;line-height:44px}.van-tree-select__item--active{color:#f44}.van-tree-select__item--disabled{color:#999}.van-tree-select__selected{position:absolute;top:0;right:15px;bottom:0;height:24px;margin:auto 0;line-height:24px}
...\ No newline at end of file ...\ No newline at end of file
1 @import '../common/index.wxss';.van-tree-select{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;font-size:14px;font-size:var(--tree-select-font-size,14px)}.van-tree-select__nav{-webkit-flex:1;flex:1;background-color:#fafafa;background-color:var(--tree-select-nav-background-color,#fafafa);--sidebar-padding:12px 8px 12px 12px}.van-tree-select__nav__inner{width:100%!important;height:100%}.van-tree-select__content{-webkit-flex:2;flex:2;background-color:#fff;background-color:var(--tree-select-content-background-color,#fff)}.van-tree-select__item{position:relative;font-weight:700;padding:0 32px 0 16px;padding:0 32px 0 var(--padding-md,16px);line-height:44px;line-height:var(--tree-select-item-height,44px)}.van-tree-select__item--active{color:#ee0a24;color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:#c8c9cc;color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:16px;right:var(--padding-md,16px)}
...\ No newline at end of file ...\ No newline at end of file
......
1 import { VantComponent } from '../common/component';
2 import { isImageFile } from './utils';
3 import { addUnit } from '../common/utils';
4 VantComponent({
5 props: {
6 disabled: Boolean,
7 multiple: Boolean,
8 uploadText: String,
9 previewSize: {
10 type: null,
11 value: 90,
12 observer: 'setComputedPreviewSize'
13 },
14 name: {
15 type: [Number, String],
16 value: ''
17 },
18 accept: {
19 type: String,
20 value: 'image'
21 },
22 fileList: {
23 type: Array,
24 value: [],
25 observer: 'formatFileList'
26 },
27 maxSize: {
28 type: Number,
29 value: Number.MAX_VALUE
30 },
31 maxCount: {
32 type: Number,
33 value: 100
34 },
35 previewImage: {
36 type: Boolean,
37 value: true
38 },
39 previewFullImage: {
40 type: Boolean,
41 value: true
42 },
43 imageFit: {
44 type: String,
45 value: 'scaleToFill'
46 },
47 useSlot: Boolean,
48 useBeforeRead: Boolean
49 },
50 data: {
51 lists: [],
52 computedPreviewSize: '',
53 isInCount: true
54 },
55 methods: {
56 formatFileList() {
57 const { fileList = [], maxCount } = this.data;
58 const lists = fileList.map(item => (Object.assign(Object.assign({}, item), { isImage: typeof item.isImage === 'undefined'
59 ? isImageFile(item)
60 : item.isImage })));
61 this.setData({ lists, isInCount: lists.length < maxCount });
62 },
63 setComputedPreviewSize(val) {
64 this.setData({
65 computedPreviewSize: addUnit(val)
66 });
67 },
68 startUpload() {
69 if (this.data.disabled)
70 return;
71 const { name = '', capture = ['album', 'camera'], maxCount = 100, multiple = false, maxSize, accept, lists, useBeforeRead = false // 是否定义了 beforeRead
72 } = this.data;
73 let chooseFile = null;
74 const newMaxCount = maxCount - lists.length;
75 // 设置为只选择图片的时候使用 chooseImage 来实现
76 if (accept === 'image') {
77 chooseFile = new Promise((resolve, reject) => {
78 wx.chooseImage({
79 count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
80 sourceType: capture,
81 success: resolve,
82 fail: reject
83 });
84 });
85 }
86 else {
87 chooseFile = new Promise((resolve, reject) => {
88 wx.chooseMessageFile({
89 count: multiple ? newMaxCount : 1,
90 type: 'file',
91 success: resolve,
92 fail: reject
93 });
94 });
95 }
96 chooseFile.then((res) => {
97 const file = multiple ? res.tempFiles : res.tempFiles[0];
98 // 检查文件大小
99 if (file instanceof Array) {
100 const sizeEnable = file.every(item => item.size <= maxSize);
101 if (!sizeEnable) {
102 this.$emit('oversize', { name });
103 return;
104 }
105 }
106 else if (file.size > maxSize) {
107 this.$emit('oversize', { name });
108 return;
109 }
110 // 触发上传之前的钩子函数
111 if (useBeforeRead) {
112 this.$emit('before-read', {
113 file,
114 name,
115 callback: (result) => {
116 if (result) {
117 // 开始上传
118 this.$emit('after-read', { file, name });
119 }
120 }
121 });
122 }
123 else {
124 this.$emit('after-read', { file, name });
125 }
126 });
127 },
128 deleteItem(event) {
129 const { index } = event.currentTarget.dataset;
130 this.$emit('delete', { index, name: this.data.name });
131 },
132 doPreviewImage(event) {
133 if (!this.data.previewFullImage)
134 return;
135 const curUrl = event.currentTarget.dataset.url;
136 const images = this.data.lists
137 .filter(item => item.isImage)
138 .map(item => item.url || item.path);
139 this.$emit('click-preview', { url: curUrl, name: this.data.name });
140 wx.previewImage({
141 urls: images,
142 current: curUrl,
143 fail() {
144 wx.showToast({ title: '预览图片失败', icon: 'none' });
145 }
146 });
147 }
148 }
149 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="van-uploader"
5 >
6 <view class="van-uploader__wrapper">
7 <!-- 预览样式 -->
8 <block wx:if="{{ previewImage }}">
9 <view
10 wx:for="{{ lists }}"
11 wx:key="{{ index }}"
12 class="van-uploader__preview"
13 >
14 <image
15 wx:if="{{ item.isImage }}"
16 mode="{{ imageFit }}"
17 src="{{ item.url || item.path }}"
18 alt="{{ item.name || ('图片' + index) }}"
19 class="van-uploader__preview-image"
20 style="width: {{ computedPreviewSize }}px; height: {{ computedPreviewSize }}px;"
21 data-url="{{ item.url || item.path }}"
22 bind:tap="doPreviewImage"
23 />
24 <view
25 wx:else
26 class="van-uploader__file"
27 style="width: {{ computedPreviewSize }}px; height: {{ computedPreviewSize }}px;"
28 >
29 <van-icon name="description" class="van-uploader__file-icon" />
30 <view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url || item.path }}</view>
31 </view>
32 <van-icon
33 name="delete"
34 class="van-uploader__preview-delete"
35 bind:tap="deleteItem"
36 data-index="{{ index }}"
37 />
38 </view>
39 </block>
40 <!-- 上传样式 -->
41 <block wx:if="{{ isInCount }}">
42 <block wx:if="{{ useSlot }}">
43 <view class="van-uploader__slot" bind:tap="startUpload">
44 <slot />
45 </view>
46 </block>
47 <block wx:else>
48 <!-- 默认上传样式 -->
49 <view
50 class="van-uploader__upload"
51 style="width: {{ computedPreviewSize }}px; height: {{ computedPreviewSize }}px;"
52 bind:tap="startUpload"
53 >
54 <van-icon name="plus" class="van-uploader__upload-icon" />
55 <text wx:if="{{ uploadText }}" class="van-uploader__upload-text">{{ uploadText }}</text>
56 </view>
57 </block>
58 </block>
59 </view>
60 </view>
1 @import '../common/index.wxss';.van-uploader{position:relative;display:inline-block}.van-uploader__wrapper{display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.van-uploader__upload{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:80px;height:80px;margin:0 8px 8px 0;background-color:#fff;border:1px dashed #e5e5e5}.van-uploader__upload-icon{display:inline-block;width:24px;height:24px;color:#969799;font-size:24px}.van-uploader__upload-text{margin-top:8px;color:#969799;font-size:12px}.van-uploader__preview{position:relative;margin:0 8px 8px 0}.van-uploader__preview-image{display:block;width:80px;height:80px}.van-uploader__preview-delete{position:absolute;right:0;bottom:0;display:inline-block;width:18px;height:18px;padding:1px;color:#fff;text-align:center;background-color:rgba(0,0,0,.45)}.van-uploader__file{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;width:80px;height:80px;background-color:#f8f8f8}.van-uploader__file-icon{display:inline-block;width:20px;height:20px;color:#7d7e80;font-size:20px}.van-uploader__file-name{box-sizing:border-box;width:100%;margin-top:8px;padding:0 5px;color:#7d7e80;font-size:12px;text-align:center}
...\ No newline at end of file ...\ No newline at end of file
1 interface File {
2 path: string;
3 url: string;
4 size: number;
5 name: string;
6 type: string;
7 time: number;
8 image: boolean;
9 }
10 export declare function isImageUrl(url: string): boolean;
11 export declare function isImageFile(item: File): boolean;
12 export {};
1 const IMAGE_EXT = ['jpeg', 'jpg', 'gif', 'png', 'svg'];
2 export function isImageUrl(url) {
3 return IMAGE_EXT.some(ext => url.indexOf(`.${ext}`) !== -1);
4 }
5 export function isImageFile(item) {
6 if (item.type) {
7 return item.type.indexOf('image') === 0;
8 }
9 if (item.path) {
10 return isImageUrl(item.path);
11 }
12 if (item.url) {
13 return isImageUrl(item.url);
14 }
15 return false;
16 }
1 var bem = require('./bem.wxs').bem; 1 var bem = require('./bem.wxs').bem;
2 var memoize = require('./memoize.wxs').memoize; 2 var memoize = require('./memoize.wxs').memoize;
3 3
4 function isSrc(url) {
5 return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0;
6 }
7
8 module.exports = { 4 module.exports = {
9 bem: memoize(bem), 5 bem: memoize(bem),
10 isSrc: isSrc,
11 memoize: memoize 6 memoize: memoize
12 }; 7 };
......
...@@ -4,8 +4,6 @@ var filter = { ...@@ -4,8 +4,6 @@ var filter = {
4 var result = val * 0.01; //分到元 4 var result = val * 0.01; //分到元
5 // result += ''; //转成字符串 5 // result += ''; //转成字符串
6 // result = result.toFixed(2); //留两位小数 6 // result = result.toFixed(2); //留两位小数
7 console.log("val:",val);
8 console.log("result:",result);
9 return result.toFixed(2); 7 return result.toFixed(2);
10 }, 8 },
11 // 毫秒转格式 9 // 毫秒转格式
......