uview-plus 3.3.6 → 3.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +45 -0
- package/components/u-action-sheet/props.js +6 -1
- package/components/u-action-sheet/u-action-sheet.vue +4 -5
- package/components/u-cell/u-cell.vue +20 -1
- package/components/u-checkbox/u-checkbox.vue +28 -18
- package/components/u-code/u-code.vue +0 -5
- package/components/u-count-down/u-count-down.vue +0 -5
- package/components/u-form-item/u-form-item.vue +1 -1
- package/components/u-grid-item/u-grid-item.vue +0 -5
- package/components/u-index-list/props.js +6 -1
- package/components/u-index-list/u-index-list.vue +169 -42
- package/components/u-modal/u-modal.vue +3 -3
- package/components/u-notify/u-notify.vue +0 -5
- package/components/u-number-box/u-number-box.vue +1 -0
- package/components/u-parse/node/node.vue +1 -1
- package/components/u-parse/u-parse.vue +1 -7
- package/components/u-picker/u-picker.vue +1 -0
- package/components/u-popup/u-popup.vue +3 -1
- package/components/u-row-notice/u-row-notice.vue +1 -8
- package/components/u-scroll-list/nvue.js +1 -1
- package/components/u-scroll-list/u-scroll-list.vue +5 -2
- package/components/u-slider/props.js +45 -19
- package/components/u-slider/u-slider.vue +376 -7
- package/components/u-sticky/u-sticky.vue +0 -5
- package/components/u-swipe-action-item/nvue.js +0 -5
- package/components/u-tabs/u-tabs.vue +11 -3
- package/components/u-toast/u-toast.vue +10 -10
- package/components/u-upload/u-upload.vue +9 -4
- package/components/u-upload/utils.js +10 -4
- package/components/u-waterfall/u-waterfall.vue +1 -1
- package/libs/config/props/actionSheet.js +2 -1
- package/libs/config/props/indexList.js +2 -1
- package/libs/config/props/slider.js +3 -1
- package/libs/css/common.scss +1 -1
- package/libs/mixin/mixin.js +1 -7
- package/package.json +1 -1
- package/types/index.d.ts +155 -29
- package/components/u-slider/nvue - /345/211/257/346/234/254.js" +0 -180
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
:style="[addStyle(itemStyle), {flex: scrollable ? '' : 1}]"
|
|
25
25
|
:class="[`u-tabs__wrapper__nav__item-${index}`, item.disabled && 'u-tabs__wrapper__nav__item--disabled']"
|
|
26
26
|
>
|
|
27
|
-
<
|
|
27
|
+
<slot v-if="$slots.content" name="content" :item="item" :keyName="keyName" :index="index" />
|
|
28
|
+
<slot v-else-if="!$slots.content && ($slots.default || $slots.$default)"
|
|
29
|
+
:item="item" :keyName="keyName" :index="index" />
|
|
30
|
+
<text v-else
|
|
28
31
|
:class="[item.disabled && 'u-tabs__wrapper__nav__item__text--disabled']"
|
|
29
32
|
class="u-tabs__wrapper__nav__item__text"
|
|
30
33
|
:style="[textStyle(index)]"
|
|
@@ -157,7 +160,7 @@
|
|
|
157
160
|
async mounted() {
|
|
158
161
|
this.init()
|
|
159
162
|
},
|
|
160
|
-
emits: ['click', 'change'],
|
|
163
|
+
emits: ['click', 'change', 'update:current'],
|
|
161
164
|
methods: {
|
|
162
165
|
addStyle,
|
|
163
166
|
addUnit,
|
|
@@ -209,6 +212,7 @@
|
|
|
209
212
|
if (item.disabled) return
|
|
210
213
|
this.innerCurrent = index
|
|
211
214
|
this.resize()
|
|
215
|
+
this.$emit('update:current', index)
|
|
212
216
|
this.$emit('change', {
|
|
213
217
|
...item,
|
|
214
218
|
index
|
|
@@ -327,10 +331,12 @@
|
|
|
327
331
|
@include flex;
|
|
328
332
|
align-items: center;
|
|
329
333
|
justify-content: center;
|
|
334
|
+
/* #ifdef H5 */
|
|
330
335
|
cursor: pointer;
|
|
336
|
+
/* #endif */
|
|
331
337
|
|
|
332
338
|
&--disabled {
|
|
333
|
-
/* #
|
|
339
|
+
/* #ifdef H5 */
|
|
334
340
|
cursor: not-allowed;
|
|
335
341
|
/* #endif */
|
|
336
342
|
}
|
|
@@ -338,7 +344,9 @@
|
|
|
338
344
|
&__text {
|
|
339
345
|
font-size: 15px;
|
|
340
346
|
color: $u-content-color;
|
|
347
|
+
/* #ifndef APP-NVUE */
|
|
341
348
|
white-space: nowrap !important;
|
|
349
|
+
/* #endif */
|
|
342
350
|
|
|
343
351
|
&--disabled {
|
|
344
352
|
color: $u-disabled-color !important;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<view class="u-toast">
|
|
3
3
|
<u-overlay
|
|
4
4
|
:show="isShow"
|
|
5
|
+
:zIndex="tmpConfig.overlay ? 10070 : -1"
|
|
5
6
|
:custom-style="overlayStyle"
|
|
6
7
|
>
|
|
7
8
|
<view
|
|
@@ -54,7 +55,7 @@
|
|
|
54
55
|
* @property {String} icon 图标,或者绝对路径的图片
|
|
55
56
|
* @property {String} type 主题类型 (默认 default)
|
|
56
57
|
* @property {Boolean} show 是否显示该组件 (默认 false)
|
|
57
|
-
* @property {Boolean} overlay 是否显示透明遮罩,防止点击穿透 (默认
|
|
58
|
+
* @property {Boolean} overlay 是否显示透明遮罩,防止点击穿透 (默认 true )
|
|
58
59
|
* @property {String} position 位置 (默认 'center' )
|
|
59
60
|
* @property {Object} params 跳转的参数
|
|
60
61
|
* @property {String | Number} duration 展示时间,单位ms (默认 2000 )
|
|
@@ -80,7 +81,7 @@
|
|
|
80
81
|
icon: true, // 显示的图标
|
|
81
82
|
position: 'center', // toast出现的位置
|
|
82
83
|
complete: null, // 执行完后的回调函数
|
|
83
|
-
overlay:
|
|
84
|
+
overlay: true, // 是否防止触摸穿透
|
|
84
85
|
loading: false, // 是否加载中状态
|
|
85
86
|
},
|
|
86
87
|
tmpConfig: {}, // 将用户配置和内置配置合并后的临时配置变量
|
|
@@ -92,10 +93,14 @@
|
|
|
92
93
|
if(!this.tmpConfig.icon || this.tmpConfig.icon == 'none') {
|
|
93
94
|
return '';
|
|
94
95
|
}
|
|
95
|
-
if (
|
|
96
|
-
|
|
96
|
+
if (this.tmpConfig.icon === true) {
|
|
97
|
+
if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) {
|
|
98
|
+
return type2icon(this.tmpConfig.type)
|
|
99
|
+
} else {
|
|
100
|
+
return ''
|
|
101
|
+
}
|
|
97
102
|
} else {
|
|
98
|
-
return
|
|
103
|
+
return this.tmpConfig.icon
|
|
99
104
|
}
|
|
100
105
|
},
|
|
101
106
|
overlayStyle() {
|
|
@@ -178,12 +183,7 @@
|
|
|
178
183
|
this.timer = null
|
|
179
184
|
}
|
|
180
185
|
},
|
|
181
|
-
// #ifdef VUE2
|
|
182
|
-
beforeDestroy() {
|
|
183
|
-
// #endif
|
|
184
|
-
// #ifdef VUE3
|
|
185
186
|
beforeUnmount() {
|
|
186
|
-
// #endif
|
|
187
187
|
this.clearTimer()
|
|
188
188
|
}
|
|
189
189
|
}
|
|
@@ -94,7 +94,13 @@
|
|
|
94
94
|
|
|
95
95
|
<template v-if="isInCount">
|
|
96
96
|
<view
|
|
97
|
-
v-if="$slots.
|
|
97
|
+
v-if="$slots.trigger"
|
|
98
|
+
@tap="chooseFile"
|
|
99
|
+
>
|
|
100
|
+
<slot name="trigger" />
|
|
101
|
+
</view>
|
|
102
|
+
<view
|
|
103
|
+
v-else-if="!$slots.trigger && ($slots.default || $slots.$default)"
|
|
98
104
|
@tap="chooseFile"
|
|
99
105
|
>
|
|
100
106
|
<slot />
|
|
@@ -123,7 +129,6 @@
|
|
|
123
129
|
</view>
|
|
124
130
|
</template>
|
|
125
131
|
</view>
|
|
126
|
-
|
|
127
132
|
</view>
|
|
128
133
|
</template>
|
|
129
134
|
|
|
@@ -332,7 +337,7 @@
|
|
|
332
337
|
});
|
|
333
338
|
},
|
|
334
339
|
onPreviewVideo(event) {
|
|
335
|
-
if (!this.
|
|
340
|
+
if (!this.previewFullImage) return;
|
|
336
341
|
const {
|
|
337
342
|
index
|
|
338
343
|
} = event.currentTarget.dataset;
|
|
@@ -360,7 +365,7 @@
|
|
|
360
365
|
index
|
|
361
366
|
} = event.currentTarget.dataset;
|
|
362
367
|
const item = this.data.lists[index];
|
|
363
|
-
if (!this.
|
|
368
|
+
if (!this.previewFullImage) return;
|
|
364
369
|
switch (item.type) {
|
|
365
370
|
case 'video':
|
|
366
371
|
this.onPreviewVideo(event);
|
|
@@ -19,7 +19,8 @@ function formatImage(res) {
|
|
|
19
19
|
thumb: item.path,
|
|
20
20
|
size: item.size,
|
|
21
21
|
// #ifdef H5
|
|
22
|
-
name: item.name
|
|
22
|
+
name: item.name,
|
|
23
|
+
file: item
|
|
23
24
|
// #endif
|
|
24
25
|
}))
|
|
25
26
|
}
|
|
@@ -33,7 +34,8 @@ function formatVideo(res) {
|
|
|
33
34
|
thumb: res.thumbTempFilePath,
|
|
34
35
|
size: res.size,
|
|
35
36
|
// #ifdef H5
|
|
36
|
-
name: res.name
|
|
37
|
+
name: res.name,
|
|
38
|
+
file: res
|
|
37
39
|
// #endif
|
|
38
40
|
}
|
|
39
41
|
]
|
|
@@ -45,7 +47,10 @@ function formatMedia(res) {
|
|
|
45
47
|
type: res.type,
|
|
46
48
|
url: item.tempFilePath,
|
|
47
49
|
thumb: res.type === 'video' ? item.thumbTempFilePath : item.tempFilePath,
|
|
48
|
-
size: item.size
|
|
50
|
+
size: item.size,
|
|
51
|
+
// #ifdef H5
|
|
52
|
+
file: item
|
|
53
|
+
// #endif
|
|
49
54
|
}))
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -56,7 +61,8 @@ function formatFile(res) {
|
|
|
56
61
|
size:item.size,
|
|
57
62
|
// #ifdef H5
|
|
58
63
|
name: item.name,
|
|
59
|
-
type: item.type
|
|
64
|
+
type: item.type,
|
|
65
|
+
file: item
|
|
60
66
|
// #endif
|
|
61
67
|
}))
|
|
62
68
|
}
|
package/libs/css/common.scss
CHANGED
package/libs/mixin/mixin.js
CHANGED
|
@@ -151,13 +151,7 @@ export const mixin = defineMixin({
|
|
|
151
151
|
onReachBottom() {
|
|
152
152
|
uni.$emit('uOnReachBottom')
|
|
153
153
|
},
|
|
154
|
-
|
|
155
|
-
// beforeDestroy()
|
|
156
|
-
// #endif
|
|
157
|
-
// #ifdef VUE3
|
|
158
|
-
beforeUnmount()
|
|
159
|
-
// #endif
|
|
160
|
-
{
|
|
154
|
+
beforeUnmount() {
|
|
161
155
|
// 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况
|
|
162
156
|
// 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
|
|
163
157
|
if (this.parent && test.array(this.parent.children)) {
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,35 +1,161 @@
|
|
|
1
1
|
/// <reference path="./comps.d.ts" />
|
|
2
2
|
declare module 'uview-plus' {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
3
|
+
export function install(): void //必要
|
|
4
|
+
interface test {
|
|
5
|
+
/** 邮箱格式校验 */
|
|
6
|
+
email(email: string): boolean
|
|
7
|
+
/** 手机号校验 */
|
|
8
|
+
mobile(phone: number): boolean;
|
|
9
|
+
/** url路径验证 */
|
|
10
|
+
url(value: string): boolean;
|
|
11
|
+
/** 验证日期格式 */
|
|
12
|
+
date(value: string | number): boolean;
|
|
13
|
+
/** 验证ISO类型的日期格式 YYYY-MM-DD | YYYY/MM/DD */
|
|
14
|
+
dateISO(value: string): boolean;
|
|
15
|
+
/** 验证十进制数字 */
|
|
16
|
+
number(value: number): boolean;
|
|
17
|
+
/** 验证字符串 */
|
|
18
|
+
string(value: string): boolean;
|
|
19
|
+
/** 验证整数 */
|
|
20
|
+
digits(value: number): boolean;
|
|
21
|
+
/** 验证身份证号码 */
|
|
22
|
+
idCard(value: string | number): boolean;
|
|
23
|
+
/** 是否车牌号 */
|
|
24
|
+
carNo(value: string): boolean;
|
|
25
|
+
/** 金额,只允许2位小数 */
|
|
26
|
+
amount(value: string | number): boolean;
|
|
27
|
+
/** 校验是否是中文 */
|
|
28
|
+
chinese(value: any): boolean;
|
|
29
|
+
/** 校验是否是字母 */
|
|
30
|
+
letter(value: any): boolean;
|
|
31
|
+
/** 校验字母或者数字 */
|
|
32
|
+
enOrNum(value: any): boolean;
|
|
33
|
+
/** 验证是否包含某个值 */
|
|
34
|
+
contains(source: string, value: string): boolean;
|
|
35
|
+
/** 验证一个值范围[min, max] */
|
|
36
|
+
range(value: string, between: number[]): boolean;
|
|
37
|
+
/** 验证一个长度范围[min, max] */
|
|
38
|
+
rangeLength(value: string, between: number[]): boolean;
|
|
39
|
+
/** 是否固定电话 */
|
|
40
|
+
landline(value: string | number): boolean;
|
|
41
|
+
/** 判断是否为空 */
|
|
42
|
+
empty(value: string | number | undefined | boolean | object | null): boolean;
|
|
43
|
+
/** 是否json字符串 */
|
|
44
|
+
jsonString(value: string): boolean;
|
|
45
|
+
/** 是否数组 */
|
|
46
|
+
array(value: any): boolean;
|
|
47
|
+
/** 是否对象 */
|
|
48
|
+
object(value: any): boolean;
|
|
49
|
+
/** 是否短信验证码 */
|
|
50
|
+
code(value: any, len: number): boolean;
|
|
51
|
+
/** 是否函数方法 */
|
|
52
|
+
func(value: any): boolean;
|
|
53
|
+
/** 是否promise对象 */
|
|
54
|
+
promise(value: any): boolean;
|
|
55
|
+
/** 是否图片格式 */
|
|
56
|
+
image(value: string): boolean;
|
|
57
|
+
/** 是否视频格式 */
|
|
58
|
+
video(value: string): boolean;
|
|
59
|
+
/** 是否为正则对象 */
|
|
60
|
+
regExp(value: any): boolean;
|
|
61
|
+
}
|
|
62
|
+
interface RouteParam {
|
|
63
|
+
type: 'navigateTo' | 'redirect' | 'switchTab' | 'reLaunch' | 'navigateBack';
|
|
64
|
+
/** 路由地址 */
|
|
65
|
+
url: string;
|
|
66
|
+
/** navigateBack页面后退时,回退的层数 */
|
|
67
|
+
delta?: number;
|
|
68
|
+
/** 传递的参数 */
|
|
69
|
+
params?: {};
|
|
70
|
+
/** 窗口动画,只在APP有效 */
|
|
71
|
+
animationType?: string;
|
|
72
|
+
/** 窗口动画持续时间,单位毫秒,只在APP有效 */
|
|
73
|
+
animationDuration?: number;
|
|
74
|
+
/** 是否需要拦截 */
|
|
75
|
+
intercept?: boolean;
|
|
76
|
+
}
|
|
77
|
+
interface Config {
|
|
78
|
+
v: string;
|
|
79
|
+
version: string;
|
|
80
|
+
type: ['primary', 'success', 'info', 'error', 'warning'];
|
|
81
|
+
color: Record<'u-primary' | 'u-warning' | 'u-success' | 'u-error' | 'u-info' | 'u-main-color' | 'u-content-color' | 'u-tips-color' | 'u-light-color', string>;
|
|
82
|
+
unit: 'px'
|
|
83
|
+
}
|
|
84
|
+
interface Color {
|
|
85
|
+
primary: string,
|
|
86
|
+
info: string,
|
|
87
|
+
default: string,
|
|
88
|
+
warning: string,
|
|
89
|
+
error: string,
|
|
90
|
+
success: string,
|
|
91
|
+
mainColor: string,
|
|
92
|
+
contentColor: string,
|
|
93
|
+
tipsColor: string,
|
|
94
|
+
lightColor: string,
|
|
95
|
+
borderColor: string
|
|
96
|
+
}
|
|
97
|
+
interface GlobalConfig {
|
|
98
|
+
config: Config;
|
|
99
|
+
props: {};
|
|
100
|
+
}
|
|
101
|
+
interface $u {
|
|
102
|
+
route: (url: string | RouteParam) => void;
|
|
103
|
+
/**
|
|
104
|
+
* 求两个颜色之间的渐变值
|
|
105
|
+
* @param {string} startColor 开始的颜色
|
|
106
|
+
* @param {string} endColor 结束的颜色
|
|
107
|
+
* @param {number} step 颜色等分的份额
|
|
108
|
+
*/
|
|
109
|
+
colorGradient: (startColor: string, endColor: string, step: number) => any[];
|
|
110
|
+
/**
|
|
111
|
+
* 将hex表示方式转换为rgb
|
|
112
|
+
* @param color "#000000"-> "rgb(0,0,0)" | "rgb(0,0,0)" -> "#000000"
|
|
113
|
+
* @param str 是否返回颜色数组 true -> 不返回
|
|
114
|
+
* @returns
|
|
115
|
+
*/
|
|
116
|
+
hexToRgb: (color: string, str?: boolean) => any[];
|
|
117
|
+
/**
|
|
118
|
+
* 将rgb表示方式转换为hex
|
|
119
|
+
*/
|
|
120
|
+
rgbToHex: (color: string) => string;
|
|
121
|
+
/**
|
|
122
|
+
* 十六进制转换为rgb或rgba
|
|
123
|
+
* @param color
|
|
124
|
+
* @param alpha 透明度
|
|
125
|
+
* @returns rgba(255,255,255,0.5)字符串
|
|
126
|
+
*/
|
|
127
|
+
colorToRgba: (color: string, alpha: number) => string;
|
|
128
|
+
test: test;
|
|
129
|
+
type: {},
|
|
130
|
+
http: {},
|
|
131
|
+
config: Config;
|
|
132
|
+
zIndex: {
|
|
133
|
+
toast: number;
|
|
134
|
+
noNetwork: number;
|
|
135
|
+
// popup包含popup,actionsheet,keyboard,picker的值
|
|
136
|
+
popup: number;
|
|
137
|
+
mask: number;
|
|
138
|
+
navbar: number;
|
|
139
|
+
topTips: number;
|
|
140
|
+
sticky: number;
|
|
141
|
+
indexListSticky: number;
|
|
142
|
+
},
|
|
143
|
+
debounce: (func, wait, immediate) => void;
|
|
144
|
+
throttle: (func, wait, immediate) => void;
|
|
145
|
+
mixin: {},
|
|
146
|
+
mpMixin: {},
|
|
147
|
+
props: {},
|
|
148
|
+
color: Color;
|
|
149
|
+
platform: string;
|
|
150
|
+
}
|
|
27
151
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
152
|
+
export function setConfig(config: GlobalConfig): void;
|
|
153
|
+
|
|
154
|
+
global {
|
|
155
|
+
interface Uni {
|
|
156
|
+
$u: $u
|
|
157
|
+
}
|
|
158
|
+
}
|
|
33
159
|
}
|
|
34
160
|
declare type UniCountDownRef = typeof import('./comps/countDown')['CountDownRef']
|
|
35
161
|
declare type UniCountToRef = typeof import('./comps/countTo')['CountToRef']
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 使用bindingx方案实现slider
|
|
3
|
-
* 只能使用于nvue下
|
|
4
|
-
*/
|
|
5
|
-
// 引入bindingx,此库类似于微信小程序wxs,目的是让js运行在视图层,减少视图层和逻辑层的通信折损
|
|
6
|
-
const BindingX = uni.requireNativePlugin('bindingx')
|
|
7
|
-
// nvue操作dom的库,用于获取dom的尺寸信息
|
|
8
|
-
const dom = uni.requireNativePlugin('dom')
|
|
9
|
-
// nvue中用于操作元素动画的库,类似于uni.animation,只不过uni.animation不能用于nvue
|
|
10
|
-
const animation = uni.requireNativePlugin('animation')
|
|
11
|
-
import { range } from '../../libs/function/index';
|
|
12
|
-
export default {
|
|
13
|
-
data() {
|
|
14
|
-
return {
|
|
15
|
-
// bindingx的回调值,用于取消绑定
|
|
16
|
-
panEvent: null,
|
|
17
|
-
// 标记是否移动状态
|
|
18
|
-
moving: false,
|
|
19
|
-
// 位移的偏移量
|
|
20
|
-
x: 0,
|
|
21
|
-
// 是否正在触摸过程中,用于标记动画类是否添加或移除
|
|
22
|
-
touching: false,
|
|
23
|
-
changeFromInside: false
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
watch: {
|
|
27
|
-
// 监听vlaue的变化,此变化可能是由于内部修改v-model的值,或者外部
|
|
28
|
-
// 从服务端获取一个值后,赋值给slider的v-model而导致的
|
|
29
|
-
value(n) {
|
|
30
|
-
if (!this.changeFromInside) {
|
|
31
|
-
this.initX()
|
|
32
|
-
} else {
|
|
33
|
-
this.changeFromInside = false
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
mounted() {
|
|
38
|
-
this.init()
|
|
39
|
-
},
|
|
40
|
-
methods: {
|
|
41
|
-
init() {
|
|
42
|
-
this.getSliderRect()
|
|
43
|
-
},
|
|
44
|
-
// 获取节点信息
|
|
45
|
-
// 获取slider尺寸
|
|
46
|
-
getSliderRect() {
|
|
47
|
-
// 获取滑块条的尺寸信息
|
|
48
|
-
// 通过nvue的dom模块,查询节点信息
|
|
49
|
-
setTimeout(() => {
|
|
50
|
-
dom.getComponentRect(this.$refs['slider'], res => {
|
|
51
|
-
this.sliderRect = res.size
|
|
52
|
-
this.initX()
|
|
53
|
-
})
|
|
54
|
-
}, 10)
|
|
55
|
-
},
|
|
56
|
-
// 初始化按钮位置
|
|
57
|
-
initButtonStyle({
|
|
58
|
-
barStyle,
|
|
59
|
-
buttonWrapperStyle
|
|
60
|
-
}) {
|
|
61
|
-
this.barStyle = barStyle
|
|
62
|
-
this.buttonWrapperStyle = buttonWrapperStyle
|
|
63
|
-
},
|
|
64
|
-
emitEvent(event, value) {
|
|
65
|
-
this.$emit(event, value ? value : this.value)
|
|
66
|
-
},
|
|
67
|
-
formatStep(value) {
|
|
68
|
-
// 移动点占总长度的百分比
|
|
69
|
-
return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step
|
|
70
|
-
},
|
|
71
|
-
// 滑动开始
|
|
72
|
-
onTouchStart(e) {
|
|
73
|
-
// 阻止页面滚动,可以保证在滑动过程中,不让页面可以上下滚动,造成不好的体验
|
|
74
|
-
e.stopPropagation && e.stopPropagation()
|
|
75
|
-
e.preventDefault && e.preventDefault()
|
|
76
|
-
if (this.moving || this.disabled) {
|
|
77
|
-
// 释放上一次的资源
|
|
78
|
-
if (this.panEvent?.token != 0) {
|
|
79
|
-
BindingX.unbind({
|
|
80
|
-
token: this.panEvent.token,
|
|
81
|
-
// pan为手势事件
|
|
82
|
-
eventType: 'pan'
|
|
83
|
-
})
|
|
84
|
-
this.gesToken = 0
|
|
85
|
-
}
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.moving = true
|
|
90
|
-
this.touching = true
|
|
91
|
-
|
|
92
|
-
// 获取元素ref
|
|
93
|
-
const button = this.$refs['nvue-button'].ref
|
|
94
|
-
const gap = this.$refs['nvue-gap'].ref
|
|
95
|
-
|
|
96
|
-
const {
|
|
97
|
-
min,
|
|
98
|
-
max,
|
|
99
|
-
step
|
|
100
|
-
} = this
|
|
101
|
-
const {
|
|
102
|
-
left,
|
|
103
|
-
width
|
|
104
|
-
} = this.sliderRect
|
|
105
|
-
|
|
106
|
-
// 初始值为本次偏移量x,加上次停止滑动时的结束值
|
|
107
|
-
let exporession = `(${this.x} + x)`
|
|
108
|
-
// 将偏移的x值,转为总位移的百分比值,为了和min和max进行判断
|
|
109
|
-
exporession = `(${exporession} / ${width}) * 100`
|
|
110
|
-
if (step > 1) {
|
|
111
|
-
// 如果step步进大于1,需要跳步,所以需要使用Math.round进行取整
|
|
112
|
-
exporession = `round(max(${min}, min(${exporession}, ${max})) / ${step}) * ${step}`
|
|
113
|
-
} else {
|
|
114
|
-
// 当step=1时,无需跳步,充分利用bindingx性能,滑块实时跟随手势,达到丝滑的效果
|
|
115
|
-
exporession = `max(${min}, min(${exporession}, ${max}))`
|
|
116
|
-
}
|
|
117
|
-
// 将百分比最后转化为对应的px值
|
|
118
|
-
exporession = `${exporession} / 100 * ${width}`
|
|
119
|
-
// 最大值不允许超过轨迹的宽度
|
|
120
|
-
const {
|
|
121
|
-
sliderWidth
|
|
122
|
-
} = this.sliderRect
|
|
123
|
-
exporession = `min(${sliderWidth}, ${exporession})`
|
|
124
|
-
// 滑块点总是需要一个左偏移的值,为自身宽度的一半
|
|
125
|
-
const buttonExpression = `${exporession} - ${this.blockHeight / 2}`
|
|
126
|
-
// 阿里为了KPI而开源的BindingX
|
|
127
|
-
this.panEvent = BindingX.bind({
|
|
128
|
-
anchor: button,
|
|
129
|
-
eventType: 'pan',
|
|
130
|
-
props: [{
|
|
131
|
-
element: gap,
|
|
132
|
-
// 绑定width属性,设置其宽度值
|
|
133
|
-
property: 'width',
|
|
134
|
-
expression
|
|
135
|
-
}, {
|
|
136
|
-
element: button,
|
|
137
|
-
// 绑定width属性,设置其宽度值
|
|
138
|
-
property: 'transform.translateX',
|
|
139
|
-
expression: buttonExpression
|
|
140
|
-
}]
|
|
141
|
-
}, (e) => {
|
|
142
|
-
if (e.state === 'end' || e.state === 'exit') {
|
|
143
|
-
//
|
|
144
|
-
this.x = range(0, left + width, e.deltaX + this.x)
|
|
145
|
-
// 根据偏移值,得出移动的百分比,进而修改双向绑定的v-model的值
|
|
146
|
-
const value = (this.x / width) * 100
|
|
147
|
-
const percent = this.formatStep(value)
|
|
148
|
-
// 修改value值
|
|
149
|
-
this.$emit('input', percent)
|
|
150
|
-
// 标记下一次触发value的watch时,这个值的变化,是由内部改变的
|
|
151
|
-
this.changeFromInside = true
|
|
152
|
-
this.moving = false
|
|
153
|
-
this.touching = false
|
|
154
|
-
}
|
|
155
|
-
})
|
|
156
|
-
},
|
|
157
|
-
// 从value的变化,倒推得出x的值该为多少
|
|
158
|
-
initX() {
|
|
159
|
-
const {
|
|
160
|
-
left,
|
|
161
|
-
width
|
|
162
|
-
} = this.sliderRect
|
|
163
|
-
// 得出x的初始偏移值,之所以需要这么做,是因为在bindingX中,触摸滑动时,只能的值本次移动的偏移值
|
|
164
|
-
// 而无法的值准确的前后移动的两个点的坐标值,weex纯粹为阿里巴巴的KPI(部门业绩考核)产物,也就这样了
|
|
165
|
-
this.x = this.value / 100 * width
|
|
166
|
-
// 设置移动的值
|
|
167
|
-
const barStyle = {
|
|
168
|
-
width: this.x + 'px'
|
|
169
|
-
}
|
|
170
|
-
// 按钮的初始值
|
|
171
|
-
const buttonWrapperStyle = {
|
|
172
|
-
transform: `translateX(${this.x - this.blockHeight / 2}px)`
|
|
173
|
-
}
|
|
174
|
-
this.initButtonStyle({
|
|
175
|
-
barStyle,
|
|
176
|
-
buttonWrapperStyle
|
|
177
|
-
})
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|