@mpxjs/webpack-plugin 2.8.21 → 2.8.23-alpha
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/README.md +1 -1
- package/lib/config.js +14 -0
- package/lib/dependencies/AddEntryDependency.js +24 -0
- package/lib/dependencies/DynamicEntryDependency.js +14 -1
- package/lib/dependencies/ResolveDependency.js +4 -0
- package/lib/index.js +52 -7
- package/lib/loader.js +40 -0
- package/lib/platform/template/wx/component-config/button.js +14 -2
- package/lib/platform/template/wx/component-config/image.js +4 -0
- package/lib/platform/template/wx/component-config/input.js +4 -0
- package/lib/platform/template/wx/component-config/rich-text.js +4 -0
- package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
- package/lib/platform/template/wx/component-config/switch.js +4 -0
- package/lib/platform/template/wx/component-config/text.js +4 -0
- package/lib/platform/template/wx/component-config/textarea.js +5 -0
- package/lib/platform/template/wx/component-config/view.js +4 -0
- package/lib/platform/template/wx/index.js +121 -1
- package/lib/resolve-loader.js +4 -1
- package/lib/runtime/components/tenon/getInnerListeners.js +314 -0
- package/lib/runtime/components/tenon/tenon-button.vue +305 -0
- package/lib/runtime/components/tenon/tenon-image.vue +61 -0
- package/lib/runtime/components/tenon/tenon-input.vue +104 -0
- package/lib/runtime/components/tenon/tenon-rich-text.vue +21 -0
- package/lib/runtime/components/tenon/tenon-scroll-view.vue +124 -0
- package/lib/runtime/components/tenon/tenon-switch.vue +91 -0
- package/lib/runtime/components/tenon/tenon-text-area.vue +77 -0
- package/lib/runtime/components/tenon/tenon-text.vue +64 -0
- package/lib/runtime/components/tenon/tenon-view.vue +93 -0
- package/lib/runtime/optionProcessor.tenon.js +388 -0
- package/lib/style-compiler/index.js +1 -1
- package/lib/style-compiler/plugins/hm.js +20 -0
- package/lib/template-compiler/compiler.js +11 -2
- package/lib/tenon/index.js +104 -0
- package/lib/tenon/processJSON.js +356 -0
- package/lib/tenon/processScript.js +262 -0
- package/lib/tenon/processStyles.js +21 -0
- package/lib/tenon/processTemplate.js +133 -0
- package/lib/utils/get-relative-path.js +25 -0
- package/package.json +5 -2
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { isEmptyObject } from '../../utils'
|
|
2
|
+
|
|
3
|
+
const tapEvents = [
|
|
4
|
+
'onTouchstart',
|
|
5
|
+
'onTouchmove',
|
|
6
|
+
'onTouchcancel',
|
|
7
|
+
'onTouchend',
|
|
8
|
+
'onLongtap'
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
function createTouch (context, hasLongTap, __mpxTapInfo) {
|
|
12
|
+
return ({
|
|
13
|
+
onTouch (e) {
|
|
14
|
+
// 用touch模拟longtap
|
|
15
|
+
switch (e.state) {
|
|
16
|
+
case 1:
|
|
17
|
+
context.$emit('touchstart', e)
|
|
18
|
+
__mpxTapInfo.detail = {
|
|
19
|
+
x: e.position.x,
|
|
20
|
+
y: e.position.y
|
|
21
|
+
}
|
|
22
|
+
__mpxTapInfo.startTimer = null
|
|
23
|
+
|
|
24
|
+
if (hasLongTap) {
|
|
25
|
+
__mpxTapInfo.startTimer = setTimeout(() => {
|
|
26
|
+
if (hasLongTap) {
|
|
27
|
+
const re = inheritEvent(
|
|
28
|
+
'longtap',
|
|
29
|
+
e,
|
|
30
|
+
__mpxTapInfo.detail
|
|
31
|
+
)
|
|
32
|
+
context.$emit('longtap', re)
|
|
33
|
+
__mpxTapInfo.startTimer = null
|
|
34
|
+
}
|
|
35
|
+
}, 350)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
break
|
|
39
|
+
case 2:
|
|
40
|
+
context.$emit('touchmove', e)
|
|
41
|
+
if (
|
|
42
|
+
Math.abs(e.position.x - __mpxTapInfo.detail.x) > 1 ||
|
|
43
|
+
Math.abs(e.position.y - __mpxTapInfo.detail.y) > 1
|
|
44
|
+
) {
|
|
45
|
+
__mpxTapInfo.startTimer &&
|
|
46
|
+
clearTimeout(__mpxTapInfo.startTimer)
|
|
47
|
+
__mpxTapInfo.startTimer = null
|
|
48
|
+
}
|
|
49
|
+
break
|
|
50
|
+
case 3:
|
|
51
|
+
context.$emit('touchend', e)
|
|
52
|
+
__mpxTapInfo.startTimer &&
|
|
53
|
+
clearTimeout(__mpxTapInfo.startTimer)
|
|
54
|
+
__mpxTapInfo.startTimer = null
|
|
55
|
+
break
|
|
56
|
+
case 4:
|
|
57
|
+
context.$emit('touchcancel', e)
|
|
58
|
+
break
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function processOriginEvent (listeners) {
|
|
65
|
+
// 给event添加_originEvent属性
|
|
66
|
+
const ignoreEvents = ['onTap', 'onFocus', 'onChange', 'onBlur', 'onConfirm']
|
|
67
|
+
Object.keys(listeners).forEach((key) => {
|
|
68
|
+
if (!ignoreEvents.includes(key)) {
|
|
69
|
+
const listener = listeners[key]
|
|
70
|
+
listeners[key] = function (e) {
|
|
71
|
+
if (e) {
|
|
72
|
+
e._originEvent = { ...e }
|
|
73
|
+
}
|
|
74
|
+
listener.call(this, e)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function processModel (listeners, context) {
|
|
81
|
+
// 该函数只有wx:model的情况下才调用,而且默认e.detail.value有值
|
|
82
|
+
// 该函数必须在产生merge前执行
|
|
83
|
+
// todo 此处对于$attrs的访问会导致父组件更新时子组件必然更新,暂时用短路效应避免影响,待优化
|
|
84
|
+
// todo 访问$listeners也会导致上述现象,但是为了事件代理还必须访问$listeners,待后续思考处理
|
|
85
|
+
|
|
86
|
+
const modelEvent = context.$attrs.mpxModelEvent
|
|
87
|
+
const modelEventId = context.$attrs.mpxModelEventId
|
|
88
|
+
if (modelEvent && modelEventId) {
|
|
89
|
+
// 对于modelEvent,内部获得时间后向外部转发,触发外部listener的同时转发为mpxModel事件
|
|
90
|
+
|
|
91
|
+
const listener = listeners.onInput
|
|
92
|
+
|
|
93
|
+
listeners.onInput = function (e) {
|
|
94
|
+
Hummer.notifyCenter.triggerEvent(modelEventId, {
|
|
95
|
+
detail: e
|
|
96
|
+
})
|
|
97
|
+
context.$emit('mpxModel', {
|
|
98
|
+
detail: e
|
|
99
|
+
})
|
|
100
|
+
listener && listener.call(this, e)
|
|
101
|
+
}
|
|
102
|
+
// 内部listener不需要mpxModel
|
|
103
|
+
delete listeners.mpxModel
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function mergeListeners (listeners, otherListeners, options = {}, context, __mpxTapInfo) {
|
|
108
|
+
if (!otherListeners) {
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
// "onTouchstart",
|
|
112
|
+
// "onTouchmove",
|
|
113
|
+
// "onTouchcancel",
|
|
114
|
+
// "onTouchend",
|
|
115
|
+
// "onLongtap",
|
|
116
|
+
|
|
117
|
+
// 都依赖touch事件 如果listener没有touch事件 如果是force需要强行添加一个touch事件 longTap需要根据context
|
|
118
|
+
// 特殊处理
|
|
119
|
+
const listenerMap = {}
|
|
120
|
+
tapEvents.forEach((eventName) => {
|
|
121
|
+
if (listeners[eventName]) {
|
|
122
|
+
listenerMap[eventName] = true
|
|
123
|
+
delete listeners[eventName]
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
// const otherListenerKeys = Object.keys(otherListeners)
|
|
127
|
+
// for (let key of otherListenerKeys) {
|
|
128
|
+
|
|
129
|
+
// }
|
|
130
|
+
|
|
131
|
+
Object.keys(otherListeners).forEach((key) => {
|
|
132
|
+
const listener = otherListeners[key]
|
|
133
|
+
let rawListener
|
|
134
|
+
if (tapEvents.includes(key)) {
|
|
135
|
+
// 判断onTouch是否存在 若存在 则直接处理
|
|
136
|
+
rawListener = listeners.onTouch
|
|
137
|
+
|
|
138
|
+
if (!rawListener && !options.force) {
|
|
139
|
+
return
|
|
140
|
+
} else if (!rawListener && options.force) {
|
|
141
|
+
// 创建一个touh事件 并赋值
|
|
142
|
+
listeners.onTouch = createTouch(context, listenerMap.onLongtap, __mpxTapInfo).onTouch
|
|
143
|
+
rawListener = listeners.onTouch
|
|
144
|
+
}
|
|
145
|
+
// 事件处理 onTouchstart 1 onTouchmove 2 onTouchend 3 onTouchcancel 4
|
|
146
|
+
listeners.onTouch = function (e) {
|
|
147
|
+
// const thatKey = key
|
|
148
|
+
let timer = null
|
|
149
|
+
if (key === 'onLongtap') {
|
|
150
|
+
if (e.state === 1) {
|
|
151
|
+
// start
|
|
152
|
+
timer = setTimeout(
|
|
153
|
+
() => {
|
|
154
|
+
listener.call(this, e)
|
|
155
|
+
},
|
|
156
|
+
options.before ? 340 : 360
|
|
157
|
+
)
|
|
158
|
+
} else if (e.state === 3) {
|
|
159
|
+
timer && clearTimeout(timer)
|
|
160
|
+
timer = null
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
if (options.before) {
|
|
164
|
+
if (key === 'onTouchstart' && e.state === 1) {
|
|
165
|
+
listener.call(this, e)
|
|
166
|
+
} else if (key === 'onTouchmove' && e.state === 2) {
|
|
167
|
+
listener.call(this, e)
|
|
168
|
+
} else if (key === 'onTouchend' && e.state === 3) {
|
|
169
|
+
listener.call(this, e)
|
|
170
|
+
} else if (key === 'onTouchcancel' && e.state === 4) {
|
|
171
|
+
listener.call(this, e)
|
|
172
|
+
}
|
|
173
|
+
rawListener.call(this, e)
|
|
174
|
+
} else {
|
|
175
|
+
rawListener.call(this, e)
|
|
176
|
+
if (key === 'onTouchstart' && e.state === 1) {
|
|
177
|
+
listener.call(this, e)
|
|
178
|
+
} else if (key === 'onTouchmove' && e.state === 2) {
|
|
179
|
+
listener.call(this, e)
|
|
180
|
+
} else if (key === 'onTouchend' && e.state === 3) {
|
|
181
|
+
listener.call(this, e)
|
|
182
|
+
} else if (key === 'onTouchcancel' && e.state === 4) {
|
|
183
|
+
listener.call(this, e)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
rawListener = listeners[key]
|
|
190
|
+
if (!rawListener) {
|
|
191
|
+
if (options.force) {
|
|
192
|
+
listeners[key] = listener
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
listeners[key] = function (e) {
|
|
196
|
+
if (options.before) {
|
|
197
|
+
listener.call(this, e)
|
|
198
|
+
rawListener.call(this, e)
|
|
199
|
+
} else {
|
|
200
|
+
rawListener.call(this, e)
|
|
201
|
+
listener.call(this, e)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
// 没有tap 用touch模拟 touchstart touchmove touchcancel touchend tap longpress langtap
|
|
209
|
+
function processTouchAndLtap (listeners, context, __mpxTapInfo) {
|
|
210
|
+
const listenerMap = {}
|
|
211
|
+
tapEvents.forEach((eventName) => {
|
|
212
|
+
if (listeners[eventName]) {
|
|
213
|
+
listenerMap[eventName] = true
|
|
214
|
+
delete listeners[eventName]
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
if (isEmptyObject(listenerMap)) return
|
|
218
|
+
const events = createTouch(context, listenerMap.onLongtap, __mpxTapInfo)
|
|
219
|
+
mergeListeners(
|
|
220
|
+
listeners,
|
|
221
|
+
events,
|
|
222
|
+
{
|
|
223
|
+
force: true
|
|
224
|
+
},
|
|
225
|
+
context,
|
|
226
|
+
__mpxTapInfo
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function extendEvent (e, extendObj = {}) {
|
|
231
|
+
Object.keys(extendObj).forEach((key) => {
|
|
232
|
+
Object.defineProperty(e, key, {
|
|
233
|
+
value: extendObj[key],
|
|
234
|
+
enumerable: true,
|
|
235
|
+
configurable: true,
|
|
236
|
+
writable: true
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function inheritEvent (type, oe, detail = {}) {
|
|
242
|
+
detail = Object.assign({}, oe.detail, detail)
|
|
243
|
+
const ne = getCustomEvent(type, detail)
|
|
244
|
+
extendEvent(ne, {
|
|
245
|
+
timeStamp: oe.timeStamp,
|
|
246
|
+
target: oe.target,
|
|
247
|
+
currentTarget: oe.currentTarget,
|
|
248
|
+
stopPropagation: oe.stopPropagation.bind(oe),
|
|
249
|
+
preventDefault: oe.preventDefault.bind(oe)
|
|
250
|
+
})
|
|
251
|
+
return ne
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function getCustomEvent (type, detail = {}, target = null) {
|
|
255
|
+
return {
|
|
256
|
+
type,
|
|
257
|
+
detail,
|
|
258
|
+
target,
|
|
259
|
+
timeStamp: new Date().valueOf()
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function noop () {}
|
|
264
|
+
|
|
265
|
+
function getListeners (context) {
|
|
266
|
+
const attrs = context.$attrs
|
|
267
|
+
const listeners = {}
|
|
268
|
+
Object.keys(attrs).forEach((v) => {
|
|
269
|
+
if (/^on[A-Z]/.test(v)) {
|
|
270
|
+
listeners[v] = attrs[v]
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
return listeners
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export default function getInnerListeners (context, options = {}) {
|
|
277
|
+
let {
|
|
278
|
+
mergeBefore = {},
|
|
279
|
+
mergeAfter = {},
|
|
280
|
+
defaultListeners = [],
|
|
281
|
+
ignoredListeners = []
|
|
282
|
+
} = options
|
|
283
|
+
const __mpxTapInfo = {}
|
|
284
|
+
// 从attrs里面拿到以on开头的所有绑定的事件
|
|
285
|
+
const listeners = Object.assign({}, getListeners(context))
|
|
286
|
+
defaultListeners.forEach((key) => {
|
|
287
|
+
if (!listeners[key]) listeners[key] = noop
|
|
288
|
+
})
|
|
289
|
+
const mergeBeforeOptions = {
|
|
290
|
+
before: true
|
|
291
|
+
}
|
|
292
|
+
const mergeAfterOptions = {
|
|
293
|
+
before: false
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (mergeBefore.listeners) {
|
|
297
|
+
mergeBeforeOptions.force = mergeBefore.force
|
|
298
|
+
mergeBefore = mergeBefore.listeners
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (mergeAfter.listeners) {
|
|
302
|
+
mergeAfterOptions.force = mergeAfter.force
|
|
303
|
+
mergeAfter = mergeAfter.listeners
|
|
304
|
+
}
|
|
305
|
+
processOriginEvent(listeners)
|
|
306
|
+
processModel(listeners, context)
|
|
307
|
+
processTouchAndLtap(listeners, context, __mpxTapInfo)
|
|
308
|
+
mergeListeners(listeners, mergeBefore, mergeBeforeOptions, context, __mpxTapInfo)
|
|
309
|
+
mergeListeners(listeners, mergeAfter, mergeAfterOptions, context, __mpxTapInfo)
|
|
310
|
+
ignoredListeners.forEach((key) => {
|
|
311
|
+
delete listeners[key]
|
|
312
|
+
})
|
|
313
|
+
return listeners
|
|
314
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { h } from "@hummer/tenon-vue";
|
|
3
|
+
import getInnerListeners from "./getInnerListeners";
|
|
4
|
+
|
|
5
|
+
// 获取当前小程序样式版本配置
|
|
6
|
+
const styleVersion = global.__style || "";
|
|
7
|
+
const sizeClassMap = {
|
|
8
|
+
default: "",
|
|
9
|
+
mini: "mpx-button-size-mini",
|
|
10
|
+
};
|
|
11
|
+
const typeClassMap = {
|
|
12
|
+
primary: "mpx-button-type-primary",
|
|
13
|
+
warn: "mpx-button-type-warn",
|
|
14
|
+
};
|
|
15
|
+
const plainClassMap = {
|
|
16
|
+
false: "",
|
|
17
|
+
true: "mpx-button-plain",
|
|
18
|
+
};
|
|
19
|
+
const disabledClassMap = {
|
|
20
|
+
false: "",
|
|
21
|
+
true: "mpx-button-disabled",
|
|
22
|
+
};
|
|
23
|
+
const clickDisabledClassMap = {
|
|
24
|
+
false: "",
|
|
25
|
+
true: "mpx-button-click-disabled",
|
|
26
|
+
};
|
|
27
|
+
export default (function(){
|
|
28
|
+
return {
|
|
29
|
+
name: "mpx-button",
|
|
30
|
+
data() {
|
|
31
|
+
return {
|
|
32
|
+
hover: false,
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
props: {
|
|
36
|
+
name: String,
|
|
37
|
+
size: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: "default",
|
|
40
|
+
},
|
|
41
|
+
type: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: "default",
|
|
44
|
+
},
|
|
45
|
+
plain: Boolean,
|
|
46
|
+
disabled: Boolean,
|
|
47
|
+
loading: Boolean,
|
|
48
|
+
formType: String,
|
|
49
|
+
hoverClass: {
|
|
50
|
+
type: String,
|
|
51
|
+
default: "button-hover",
|
|
52
|
+
},
|
|
53
|
+
hoverStopPropagation: {
|
|
54
|
+
type: Boolean,
|
|
55
|
+
default: false,
|
|
56
|
+
},
|
|
57
|
+
hoverStartTime: {
|
|
58
|
+
type: Number,
|
|
59
|
+
default: 20,
|
|
60
|
+
},
|
|
61
|
+
hoverStayTime: {
|
|
62
|
+
type: Number,
|
|
63
|
+
default: 70,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
computed: {
|
|
67
|
+
className() {
|
|
68
|
+
if (this.hoverClass && this.hoverClass !== "none" && this.hover) {
|
|
69
|
+
return this.hoverClass;
|
|
70
|
+
}
|
|
71
|
+
return "";
|
|
72
|
+
},
|
|
73
|
+
classNameList() {
|
|
74
|
+
let classArr = [];
|
|
75
|
+
if (this.hoverClass && this.hoverClass !== "none" && this.hover) {
|
|
76
|
+
classArr.push(this.hoverClass);
|
|
77
|
+
}
|
|
78
|
+
if (styleVersion === "v2") {
|
|
79
|
+
classArr.push(`${sizeClassMap[this.size]}${styleVersion}`);
|
|
80
|
+
classArr.push(`${typeClassMap[this.type]}${styleVersion}`);
|
|
81
|
+
classArr.push(`mpx-button-version${styleVersion}`);
|
|
82
|
+
} else {
|
|
83
|
+
classArr.push(sizeClassMap[this.size]);
|
|
84
|
+
classArr.push(typeClassMap[this.type]);
|
|
85
|
+
classArr.push(`mpx-button-version`);
|
|
86
|
+
}
|
|
87
|
+
classArr.push(plainClassMap[this.plain]);
|
|
88
|
+
classArr.push(disabledClassMap["" + !!this.disabled]);
|
|
89
|
+
// 禁用click
|
|
90
|
+
classArr.push(clickDisabledClassMap["" + !!this.disabled]);
|
|
91
|
+
return classArr;
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
render() {
|
|
95
|
+
let mergeAfter;
|
|
96
|
+
if (this.hoverClass && this.hoverClass !== "none") {
|
|
97
|
+
mergeAfter = {
|
|
98
|
+
listeners: {
|
|
99
|
+
onTouchstart: this.handleTouchstart,
|
|
100
|
+
onTouchend: this.handleTouchend,
|
|
101
|
+
},
|
|
102
|
+
force: true,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const domProps = {
|
|
106
|
+
disabled: this.disabled,
|
|
107
|
+
plain: this.plain,
|
|
108
|
+
type: this.type,
|
|
109
|
+
};
|
|
110
|
+
const data = {
|
|
111
|
+
class: ["mpx-button", ...this.classNameList],
|
|
112
|
+
...domProps,
|
|
113
|
+
...getInnerListeners(this, {
|
|
114
|
+
mergeAfter,
|
|
115
|
+
// 由于当前机制下tap事件只有存在tap监听才会触发,为了确保该组件能够触发tap,传递一个包含tap的defaultListeners用于模拟存在tap监听
|
|
116
|
+
defaultListeners: ["onTap"],
|
|
117
|
+
}),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
let text = "";
|
|
121
|
+
const nodes = this.$slots.default();
|
|
122
|
+
nodes.forEach((item) => {
|
|
123
|
+
if (item.shapeFlag === 8 && item.children) {
|
|
124
|
+
text += item.children;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return h("button", data, text);
|
|
128
|
+
},
|
|
129
|
+
methods: {
|
|
130
|
+
handleTouchstart(e) {
|
|
131
|
+
if (e.__hoverStopPropagation) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
e.__hoverStopPropagation = this.hoverStopPropagation;
|
|
135
|
+
clearTimeout(this.startTimer);
|
|
136
|
+
this.startTimer = setTimeout(() => {
|
|
137
|
+
this.hover = true;
|
|
138
|
+
}, this.hoverStartTime);
|
|
139
|
+
},
|
|
140
|
+
handleTouchend() {
|
|
141
|
+
clearTimeout(this.endTimer);
|
|
142
|
+
this.endTimer = setTimeout(() => {
|
|
143
|
+
this.hover = false;
|
|
144
|
+
}, this.hoverStayTime);
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
})()
|
|
149
|
+
</script>
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
<style lang="stylus" scoped>
|
|
154
|
+
.mpx-button-versionv2
|
|
155
|
+
width: 184px
|
|
156
|
+
line-height 1.41176471
|
|
157
|
+
font-weight: 700;
|
|
158
|
+
padding-top 8px
|
|
159
|
+
padding-bottom 8px
|
|
160
|
+
.mpx-button-version
|
|
161
|
+
width: 100%
|
|
162
|
+
line-height 2.55555556
|
|
163
|
+
cursor: pointer
|
|
164
|
+
&:after
|
|
165
|
+
border 1px solid rgba(0,0,0,.2)
|
|
166
|
+
|
|
167
|
+
.mpx-button
|
|
168
|
+
padding-left: 14px
|
|
169
|
+
padding-right: 14px
|
|
170
|
+
border none
|
|
171
|
+
outline: none
|
|
172
|
+
position relative
|
|
173
|
+
display block
|
|
174
|
+
margin-left auto
|
|
175
|
+
margin-right auto
|
|
176
|
+
margin-bottom 10px
|
|
177
|
+
box-sizing border-box
|
|
178
|
+
font-size 18px
|
|
179
|
+
text-align center
|
|
180
|
+
text-decoration none
|
|
181
|
+
border-radius 5px
|
|
182
|
+
-webkit-tap-highlight-color transparent
|
|
183
|
+
overflow hidden
|
|
184
|
+
color #000
|
|
185
|
+
background-color #f8f8f8
|
|
186
|
+
&:after
|
|
187
|
+
content " "
|
|
188
|
+
width 200%
|
|
189
|
+
height 200%
|
|
190
|
+
position absolute
|
|
191
|
+
top 0
|
|
192
|
+
left 0
|
|
193
|
+
-webkit-transform scale(.5)
|
|
194
|
+
transform scale(.5)
|
|
195
|
+
-webkit-transform-origin 0 0
|
|
196
|
+
transform-origin 0 0
|
|
197
|
+
box-sizing border-box
|
|
198
|
+
border-radius 10px
|
|
199
|
+
|
|
200
|
+
&.button-hover
|
|
201
|
+
background-color #dedede
|
|
202
|
+
|
|
203
|
+
/* 默认版本 size=mini style */
|
|
204
|
+
&.mpx-button-size-mini
|
|
205
|
+
display inline-block
|
|
206
|
+
line-height 2.3
|
|
207
|
+
font-size 13px
|
|
208
|
+
padding 0 1.34em
|
|
209
|
+
width auto
|
|
210
|
+
/* v2 size=mini style */
|
|
211
|
+
&.mpx-button-size-miniv2
|
|
212
|
+
width auto
|
|
213
|
+
padding 0 0.75em
|
|
214
|
+
line-height 2
|
|
215
|
+
font-size 16px
|
|
216
|
+
display inline-block
|
|
217
|
+
&.mpx-button-plain
|
|
218
|
+
color #353535
|
|
219
|
+
border 1px solid #353535
|
|
220
|
+
background-color transparent
|
|
221
|
+
&.mpx-button-plain.button-hover
|
|
222
|
+
background-color rgba(0, 0, 0, 0)
|
|
223
|
+
color #828282
|
|
224
|
+
border 1px solid #828282
|
|
225
|
+
|
|
226
|
+
/* 默认版本 type=primary style */
|
|
227
|
+
&.mpx-button-type-primary
|
|
228
|
+
background-color #1aad19
|
|
229
|
+
color #fff
|
|
230
|
+
&.mpx-button-type-primary.mpx-button-plain
|
|
231
|
+
color #1aad19
|
|
232
|
+
border-color #1aad19
|
|
233
|
+
background-color #fff
|
|
234
|
+
/* v2 type=primary style */
|
|
235
|
+
&.mpx-button-type-primaryv2
|
|
236
|
+
background-color #07c160
|
|
237
|
+
color #fff
|
|
238
|
+
&.mpx-button-type-primaryv2.button-hover
|
|
239
|
+
color #fff
|
|
240
|
+
background-color #06ad56
|
|
241
|
+
&.mpx-button-type-primaryv2.mpx-button-plain
|
|
242
|
+
color #06ae56
|
|
243
|
+
border-color #179c16
|
|
244
|
+
background-color #fff
|
|
245
|
+
&.mpx-button-type-primaryv2.button-hover.mpx-button-plain
|
|
246
|
+
color #06ae56
|
|
247
|
+
background-color rgba(0, 0, 0, .1)
|
|
248
|
+
|
|
249
|
+
/* 默认版本 type=warn style */
|
|
250
|
+
&.mpx-button-type-warn
|
|
251
|
+
color #fff
|
|
252
|
+
background-color #e64340
|
|
253
|
+
&.mpx-button-type-warn.mpx-button-plain
|
|
254
|
+
color #e64340
|
|
255
|
+
background-color transparent
|
|
256
|
+
border 1px solid #e64340
|
|
257
|
+
/* v2 type=warn style */
|
|
258
|
+
&.mpx-button-type-warnv2
|
|
259
|
+
color #fa5151
|
|
260
|
+
background-color #f2f2f2
|
|
261
|
+
&.mpx-button-type-warnv2.button-hover
|
|
262
|
+
background-color #d9d9d9
|
|
263
|
+
&.mpx-button-type-warnv2.mpx-button-plain
|
|
264
|
+
color #fa5151
|
|
265
|
+
background-color #fff
|
|
266
|
+
border 1px solid #e64340
|
|
267
|
+
&.mpx-button-type-warnv2.button-hover.mpx-button-plain
|
|
268
|
+
color: #f58c8d
|
|
269
|
+
border 1px solid #f58a8b
|
|
270
|
+
background-color #fff
|
|
271
|
+
|
|
272
|
+
&.mpx-button-disabled
|
|
273
|
+
color rgba(0, 0, 0, 0.18) !important
|
|
274
|
+
background-color #fafafa !important
|
|
275
|
+
border 1px solid rgba(0, 0, 0, .2) !important
|
|
276
|
+
&.mpx-button-click-disabled
|
|
277
|
+
pointer-events none
|
|
278
|
+
&.mpx-button-loading
|
|
279
|
+
&.mpx-button-type-warn
|
|
280
|
+
color rgba(255,255,255,.6)
|
|
281
|
+
background-color #ce3c39
|
|
282
|
+
&.mpx-button-type-warnv2
|
|
283
|
+
background-color #d9d9d9
|
|
284
|
+
color #fa5151
|
|
285
|
+
&.mpx-button-type-primary
|
|
286
|
+
color: rgba(255,255,255,.6);
|
|
287
|
+
background-color: #179b16;
|
|
288
|
+
&:before
|
|
289
|
+
content: " "
|
|
290
|
+
display: inline-block
|
|
291
|
+
width: 18px
|
|
292
|
+
height: 18px
|
|
293
|
+
vertical-align: middle
|
|
294
|
+
-webkit-animation: mpxButton 1s steps(12,end) infinite
|
|
295
|
+
animation: mpxButton 1s steps(12,end) infinite
|
|
296
|
+
background transparent url('data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iciIgd2lkdGg9JzEyMHB4JyBoZWlnaHQ9JzEyMHB4JyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICAgIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJub25lIiBjbGFzcz0iYmsiPjwvcmVjdD4KICAgIDxyZWN0IHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjRTlFOUU5JwogICAgICAgICAgdHJhbnNmb3JtPSdyb3RhdGUoMCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+CiAgICA8L3JlY3Q+CiAgICA8cmVjdCB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nIzk4OTY5NycKICAgICAgICAgIHRyYW5zZm9ybT0ncm90YXRlKDMwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4KICAgICAgICAgICAgICAgICByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyM5Qjk5OUEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSg2MCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+CiAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz4KICAgIDwvcmVjdD4KICAgIDxyZWN0IHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjQTNBMUEyJwogICAgICAgICAgdHJhbnNmb3JtPSdyb3RhdGUoOTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNBQkE5QUEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxMjAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNCMkIyQjInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxNTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNCQUI4QjknCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxODAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNDMkMwQzEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyMTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNDQkNCQ0InCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyNDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNEMkQyRDInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyNzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNEQURBREEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgzMDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNFMkUyRTInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgzMzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0Pgo8L3N2Zz4=') no-repeat
|
|
297
|
+
background-size: 100%
|
|
298
|
+
margin -0.2em 0.34em 0 0
|
|
299
|
+
|
|
300
|
+
@keyframes mpxButton
|
|
301
|
+
0%
|
|
302
|
+
transform: rotate3d(0, 0, 1, 0deg)
|
|
303
|
+
100%
|
|
304
|
+
transform: rotate3d(0, 0, 1, 360deg)
|
|
305
|
+
</style>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { h } from "@hummer/tenon-vue";
|
|
3
|
+
import getInnerListeners from "./getInnerListeners";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
name: "mpx-image",
|
|
7
|
+
props: {
|
|
8
|
+
src: {
|
|
9
|
+
type: String,
|
|
10
|
+
},
|
|
11
|
+
mode: {
|
|
12
|
+
type: String,
|
|
13
|
+
default: "scaleToFill",
|
|
14
|
+
},
|
|
15
|
+
lazyLoad: {
|
|
16
|
+
type: Boolean,
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
showMenuByLongpress: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
render() {
|
|
25
|
+
let resize = "";
|
|
26
|
+
switch (this.mode) {
|
|
27
|
+
case "scaleToFill":
|
|
28
|
+
resize = "stretch";
|
|
29
|
+
break;
|
|
30
|
+
case "aspectFit":
|
|
31
|
+
resize = "contain";
|
|
32
|
+
break;
|
|
33
|
+
case "aspectFill":
|
|
34
|
+
resize = "cover";
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
resize = "stretch";
|
|
38
|
+
}
|
|
39
|
+
return h("image", {
|
|
40
|
+
class: "mpx-image",
|
|
41
|
+
src: this.src,
|
|
42
|
+
resize,
|
|
43
|
+
...getInnerListeners(this)
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
data() {
|
|
47
|
+
return {};
|
|
48
|
+
},
|
|
49
|
+
pageConfig: {
|
|
50
|
+
canScroll: false,
|
|
51
|
+
},
|
|
52
|
+
methods: {
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
</script>
|
|
56
|
+
<style lang="stylus" scoped>
|
|
57
|
+
.mpx-image
|
|
58
|
+
width 300px
|
|
59
|
+
height 225px
|
|
60
|
+
display inline-block
|
|
61
|
+
</style>
|