@mpxjs/core 2.9.36 → 2.9.39
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/package.json +3 -3
- package/src/core/proxy.js +48 -2
- package/src/dynamic/astCache.js +25 -0
- package/src/dynamic/dynamicRenderMixin.js +77 -0
- package/src/dynamic/vnode/context.js +17 -0
- package/src/dynamic/vnode/css-select/cssauron.js +445 -0
- package/src/dynamic/vnode/css-select/index.js +116 -0
- package/src/dynamic/vnode/css-select/through.js +19 -0
- package/src/dynamic/vnode/css-select/tokenizer.js +371 -0
- package/src/dynamic/vnode/interpreter.js +449 -0
- package/src/dynamic/vnode/render.js +289 -0
- package/src/index.js +2 -0
- package/src/platform/builtInMixins/index.js +8 -0
- package/src/platform/builtInMixins/proxyEventMixin.js +11 -17
- package/src/platform/builtInMixins/renderHelperMixin.js +2 -2
- package/src/platform/patch/ali/getDefaultOptions.js +20 -0
- package/src/platform/patch/wx/getDefaultOptions.js +20 -0
- package/src/vuePlugin.js +19 -16
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import cssSelect from './css-select'
|
|
2
|
+
// todo: stringify wxs 模块只能放到逻辑层执行,主要还是因为生成 vdom tree 需要根据 class 去做匹配,需要看下这个代码从哪引入
|
|
3
|
+
import stringify from '@mpxjs/webpack-plugin/lib/runtime/stringify.wxs'
|
|
4
|
+
import Interpreter from './interpreter'
|
|
5
|
+
import { dash2hump, isString, error } from '@mpxjs/utils'
|
|
6
|
+
|
|
7
|
+
const deepCloneNode = function (val) {
|
|
8
|
+
return JSON.parse(JSON.stringify(val))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function simpleNormalizeChildren (children) {
|
|
12
|
+
for (let i = 0; i < children.length; i++) {
|
|
13
|
+
if (Array.isArray(children[i])) {
|
|
14
|
+
return Array.prototype.concat.apply([], children)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return children
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function _genVnodeTree (astData, contextScope, options) {
|
|
21
|
+
const { template = {}, styles = [] } = astData || {}
|
|
22
|
+
const { moduleId, location } = options || {}
|
|
23
|
+
// 解除引用
|
|
24
|
+
const templateAst = deepCloneNode(template)
|
|
25
|
+
// 获取实例 uid
|
|
26
|
+
const uid = contextScope[0]?.__mpxProxy?.uid || contextScope[0]?.uid
|
|
27
|
+
// 动态化组件 slots 通过上下文传递,相当于 props
|
|
28
|
+
const slots = contextScope[0]?.slots || {}
|
|
29
|
+
|
|
30
|
+
function createEmptyNode () {
|
|
31
|
+
return createNode('block')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function genVnodeTree (node) {
|
|
35
|
+
if (node.type === 1) {
|
|
36
|
+
// wxs 模块不需要动态渲染
|
|
37
|
+
if (node.tag === 'wxs') {
|
|
38
|
+
return createEmptyNode()
|
|
39
|
+
} else if (node.for && !node.forProcessed) {
|
|
40
|
+
return genFor(node)
|
|
41
|
+
} else if (node.if && !node.ifProcessed) {
|
|
42
|
+
return genIf(node)
|
|
43
|
+
} else if (node.tag === 'slot') {
|
|
44
|
+
return genSlot(node)
|
|
45
|
+
} else {
|
|
46
|
+
const data = genData(node)
|
|
47
|
+
let children = genChildren(node)
|
|
48
|
+
// 运行时组件的子组件都通过 slots 属性传递,样式规则在当前组件内匹配后挂载
|
|
49
|
+
if (node.dynamic) {
|
|
50
|
+
data.slots = resolveSlot(children.map(item => genVnodeWithStaticCss(deepCloneNode(item))))
|
|
51
|
+
children = []
|
|
52
|
+
}
|
|
53
|
+
return createNode(node.tag, data, children)
|
|
54
|
+
}
|
|
55
|
+
} else if (node.type === 3) {
|
|
56
|
+
return genText(node)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function evalExps (exps) {
|
|
61
|
+
const interpreter = new Interpreter(contextScope)
|
|
62
|
+
// 消除引用关系
|
|
63
|
+
let value
|
|
64
|
+
try {
|
|
65
|
+
value = interpreter.eval(JSON.parse(JSON.stringify(exps)))
|
|
66
|
+
} catch (e) {
|
|
67
|
+
const errmsg = e.message
|
|
68
|
+
console.warn(errmsg)
|
|
69
|
+
error('interprete the expression wrong: ', location, {
|
|
70
|
+
errType: 'mpx-dynamic-interprete',
|
|
71
|
+
errmsg
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
return value
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function createNode (tag, data = {}, children = []) {
|
|
78
|
+
if (Array.isArray(data)) {
|
|
79
|
+
children = data
|
|
80
|
+
data = {}
|
|
81
|
+
}
|
|
82
|
+
if (typeof tag === 'object') {
|
|
83
|
+
return tag
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 处理 for 循环产生的数组,同时清除空节点
|
|
87
|
+
children = simpleNormalizeChildren(children).filter(node => !!node?.nt)
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
nt: tag,
|
|
91
|
+
d: data,
|
|
92
|
+
c: children
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
*
|
|
98
|
+
* 样式隔离的匹配策略优化:
|
|
99
|
+
*
|
|
100
|
+
* 条件1: 子组件不能影响到父组件的样式
|
|
101
|
+
* 条件2: slot 的内容必须在父组件的上下文当中完成样式匹配
|
|
102
|
+
* 条件3: 匹配过程只能进行一次
|
|
103
|
+
*
|
|
104
|
+
* 方案一:根据 moduleId 即作用域来进行匹配
|
|
105
|
+
* 方案二:根据虚拟树来进行匹配
|
|
106
|
+
*/
|
|
107
|
+
// function createDynamicNode (moduleId, data = {}, children = []) {
|
|
108
|
+
// const { template = {}, styles = [] } = staticMap[moduleId]
|
|
109
|
+
// data.$slots = resolveSlot(children) // 将 slot 通过上下文传递到子组件的渲染流程中
|
|
110
|
+
// const vnodeTree = _genVnodeTree(template, [data], styles, moduleId)
|
|
111
|
+
// return vnodeTree
|
|
112
|
+
// }
|
|
113
|
+
|
|
114
|
+
function resolveSlot (children) {
|
|
115
|
+
const slots = {}
|
|
116
|
+
if (children.length) {
|
|
117
|
+
for (let i = 0; i < children.length; i++) {
|
|
118
|
+
const child = children[i]
|
|
119
|
+
const name = child.d?.slot
|
|
120
|
+
if (name) {
|
|
121
|
+
const slot = (slots[name] || (slots[name] = []))
|
|
122
|
+
if (child.tag === 'template') {
|
|
123
|
+
slot.push.apply(slot, child.children || [])
|
|
124
|
+
} else {
|
|
125
|
+
slot.push(child)
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
(slots.default || (slots.default = [])).push(child)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return slots
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function genData (node) {
|
|
136
|
+
const res = {
|
|
137
|
+
uid,
|
|
138
|
+
moduleId
|
|
139
|
+
}
|
|
140
|
+
if (!node.attrsList) {
|
|
141
|
+
return res
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
node.attrsList.forEach((attr) => {
|
|
145
|
+
if (attr.name === 'class' || attr.name === 'style') {
|
|
146
|
+
// class/style 的表达式为数组形式,class/style的计算过程需要放到逻辑层,主要是因为有逻辑匹配的过程去生成 vnodeTree
|
|
147
|
+
const helper = attr.name === 'class' ? stringify.stringifyClass : stringify.stringifyStyle
|
|
148
|
+
let value = ''
|
|
149
|
+
if (attr.__exp) {
|
|
150
|
+
let valueArr = evalExps(attr.__exp)
|
|
151
|
+
valueArr = Array.isArray(valueArr) ? valueArr : [valueArr]
|
|
152
|
+
value = helper(...valueArr)
|
|
153
|
+
// dynamic style + wx:show
|
|
154
|
+
const showStyle = valueArr[2]
|
|
155
|
+
if (showStyle) {
|
|
156
|
+
value = value + ';' + showStyle
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
value = attr.value
|
|
160
|
+
}
|
|
161
|
+
res[attr.name] = value
|
|
162
|
+
} else {
|
|
163
|
+
res[dash2hump(attr.name)] = attr.__exp
|
|
164
|
+
? evalExps(attr.__exp)
|
|
165
|
+
: attr.value
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
return res
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function genChildren (node) {
|
|
173
|
+
const res = []
|
|
174
|
+
const children = node.children || []
|
|
175
|
+
if (children.length) {
|
|
176
|
+
children.forEach((item) => {
|
|
177
|
+
res.push(genNode(item))
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
return res
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function genNode (node) {
|
|
184
|
+
if (node.type === 1) {
|
|
185
|
+
return genVnodeTree(node)
|
|
186
|
+
} else if (node.type === 3 && node.isComment) {
|
|
187
|
+
return ''
|
|
188
|
+
// TODO: 注释暂不处理
|
|
189
|
+
// return _genComment(node)
|
|
190
|
+
} else {
|
|
191
|
+
return genText(node) // 文本节点统一通过 _genText 来生成,type = 2(带有表达式的文本,在 mpx 统一处理为了3) || type = 3(纯文本,非注释)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function genText (node) {
|
|
196
|
+
return {
|
|
197
|
+
nt: '#text',
|
|
198
|
+
ct: node.__exp ? evalExps(node.__exp) : node.text
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function genFor (node) {
|
|
203
|
+
node.forProcessed = true
|
|
204
|
+
|
|
205
|
+
const itemKey = node.for.item || 'item'
|
|
206
|
+
const indexKey = node.for.index || 'index'
|
|
207
|
+
const scope = {
|
|
208
|
+
[itemKey]: null,
|
|
209
|
+
[indexKey]: null
|
|
210
|
+
}
|
|
211
|
+
const forExp = node.for
|
|
212
|
+
const res = []
|
|
213
|
+
let forValue = evalExps(forExp.__exp)
|
|
214
|
+
|
|
215
|
+
// 和微信的模版渲染策略保持一致:当 wx:for 的值为字符串时,会将字符串解析成字符串数组
|
|
216
|
+
if (isString(forValue)) {
|
|
217
|
+
forValue = forValue.split('')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (Array.isArray(forValue)) {
|
|
221
|
+
forValue.forEach((item, index) => {
|
|
222
|
+
// item、index 模板当中如果没申明,需要给到默认值
|
|
223
|
+
scope[itemKey] = item
|
|
224
|
+
scope[indexKey] = index
|
|
225
|
+
|
|
226
|
+
contextScope.push(scope)
|
|
227
|
+
|
|
228
|
+
// 针对 for 循环避免每次都操作的同一个 node 导致数据的污染的问题
|
|
229
|
+
res.push(deepCloneNode(genVnodeTree(deepCloneNode(node))))
|
|
230
|
+
|
|
231
|
+
contextScope.pop()
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return res
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// 对于 if 而言最终生成 <= 1 节点
|
|
239
|
+
function genIf (node) {
|
|
240
|
+
if (!node.ifConditions) {
|
|
241
|
+
node.ifConditions = []
|
|
242
|
+
return {} // 一个空节点
|
|
243
|
+
}
|
|
244
|
+
node.ifProcessed = true
|
|
245
|
+
|
|
246
|
+
const ifConditions = node.ifConditions.slice()
|
|
247
|
+
|
|
248
|
+
let res = {} // 空节点
|
|
249
|
+
for (let i = 0; i < ifConditions.length; i++) {
|
|
250
|
+
const condition = ifConditions[i]
|
|
251
|
+
// 非 else 节点
|
|
252
|
+
if (condition.ifExp) {
|
|
253
|
+
const identifierValue = evalExps(condition.__exp)
|
|
254
|
+
if (identifierValue) {
|
|
255
|
+
res = genVnodeTree(condition.block === 'self' ? node : condition.block)
|
|
256
|
+
break
|
|
257
|
+
}
|
|
258
|
+
} else { // else 节点
|
|
259
|
+
res = genVnodeTree(condition.block)
|
|
260
|
+
break
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return res
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// 暂时不支持作用域插槽
|
|
267
|
+
function genSlot (node) {
|
|
268
|
+
const data = genData(node) // 计算属性值
|
|
269
|
+
const slotName = data.name || 'default'
|
|
270
|
+
return slots[slotName] || null
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function genVnodeWithStaticCss (vnodeTree) {
|
|
274
|
+
styles.forEach((item) => {
|
|
275
|
+
const [selector, style] = item
|
|
276
|
+
const nodes = cssSelect(selector, { moduleId })(vnodeTree)
|
|
277
|
+
nodes?.forEach((node) => {
|
|
278
|
+
// todo style 合并策略问题:合并过程中缺少了权重关系 style, class 的判断,需要优化
|
|
279
|
+
node.d.style = node.d.style ? style + node.d.style : style
|
|
280
|
+
})
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
return vnodeTree
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const interpreteredVnodeTree = genVnodeTree(templateAst)
|
|
287
|
+
|
|
288
|
+
return genVnodeWithStaticCss(interpreteredVnodeTree)
|
|
289
|
+
}
|
package/src/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import pageScrollMixin from './pageScrollMixin'
|
|
|
10
10
|
import componentGenericsMixin from './componentGenericsMixin'
|
|
11
11
|
import getTabBarMixin from './getTabBarMixin'
|
|
12
12
|
import pageRouteMixin from './pageRouteMixin'
|
|
13
|
+
import { dynamicRefsMixin, dynamicRenderHelperMixin, dynamicSlotMixin } from '../../dynamic/dynamicRenderMixin'
|
|
13
14
|
|
|
14
15
|
export default function getBuiltInMixins (options, type) {
|
|
15
16
|
let bulitInMixins = []
|
|
@@ -41,6 +42,13 @@ export default function getBuiltInMixins (options, type) {
|
|
|
41
42
|
showMixin(type),
|
|
42
43
|
i18nMixin()
|
|
43
44
|
])
|
|
45
|
+
if (__mpx_dynamic_runtime__) {
|
|
46
|
+
bulitInMixins = bulitInMixins.concat([
|
|
47
|
+
dynamicRenderHelperMixin(),
|
|
48
|
+
dynamicSlotMixin(),
|
|
49
|
+
dynamicRefsMixin()
|
|
50
|
+
])
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
}
|
|
46
54
|
return bulitInMixins.filter(item => item)
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import { setByPath, error,
|
|
1
|
+
import { setByPath, error, dash2hump, collectDataset } from '@mpxjs/utils'
|
|
2
2
|
import Mpx from '../../index'
|
|
3
|
+
import contextMap from '../../dynamic/vnode/context'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function
|
|
7
|
-
const dataset = {}
|
|
8
|
-
for (const key in props) {
|
|
9
|
-
if (hasOwn(props, key)) {
|
|
10
|
-
const matched = datasetReg.exec(key)
|
|
11
|
-
if (matched) {
|
|
12
|
-
dataset[matched[1]] = props[key]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return dataset
|
|
5
|
+
function logCallbackNotFound (context, callbackName) {
|
|
6
|
+
const location = context.__mpxProxy && context.__mpxProxy.options.mpxFileResource
|
|
7
|
+
error(`Instance property [${callbackName}] is not function, please check.`, location)
|
|
17
8
|
}
|
|
18
9
|
|
|
19
10
|
export default function proxyEventMixin () {
|
|
@@ -48,6 +39,9 @@ export default function proxyEventMixin () {
|
|
|
48
39
|
}
|
|
49
40
|
const eventConfigs = target.dataset.eventconfigs || {}
|
|
50
41
|
const curEventConfig = eventConfigs[type] || eventConfigs[fallbackType] || []
|
|
42
|
+
// 如果有 mpxuid 说明是运行时组件,那么需要设置对应的上下文
|
|
43
|
+
const rootRuntimeContext = contextMap.get(target.dataset.mpxuid)
|
|
44
|
+
const context = rootRuntimeContext || this
|
|
51
45
|
let returnedValue
|
|
52
46
|
curEventConfig.forEach((item) => {
|
|
53
47
|
const callbackName = item[0]
|
|
@@ -71,10 +65,10 @@ export default function proxyEventMixin () {
|
|
|
71
65
|
}
|
|
72
66
|
})
|
|
73
67
|
: [$event]
|
|
74
|
-
if (typeof
|
|
75
|
-
returnedValue =
|
|
68
|
+
if (typeof context[callbackName] === 'function') {
|
|
69
|
+
returnedValue = context[callbackName].apply(context, params)
|
|
76
70
|
} else {
|
|
77
|
-
|
|
71
|
+
logCallbackNotFound(context, callbackName)
|
|
78
72
|
}
|
|
79
73
|
}
|
|
80
74
|
})
|
|
@@ -36,8 +36,8 @@ export default function renderHelperMixin () {
|
|
|
36
36
|
_sc (key) {
|
|
37
37
|
return (this.__mpxProxy.renderData[key] = this[key])
|
|
38
38
|
},
|
|
39
|
-
_r (skipPre) {
|
|
40
|
-
this.__mpxProxy.renderWithData(skipPre)
|
|
39
|
+
_r (skipPre, vnode) {
|
|
40
|
+
this.__mpxProxy.renderWithData(skipPre, vnode)
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -63,6 +63,26 @@ function transformApiForProxy (context, currentInject) {
|
|
|
63
63
|
}
|
|
64
64
|
})
|
|
65
65
|
}
|
|
66
|
+
if (currentInject.moduleId) {
|
|
67
|
+
Object.defineProperties(context, {
|
|
68
|
+
__moduleId: {
|
|
69
|
+
get () {
|
|
70
|
+
return currentInject.moduleId
|
|
71
|
+
},
|
|
72
|
+
configurable: false
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
if (currentInject.dynamic) {
|
|
77
|
+
Object.defineProperties(context, {
|
|
78
|
+
__dynamic: {
|
|
79
|
+
get () {
|
|
80
|
+
return currentInject.dynamic
|
|
81
|
+
},
|
|
82
|
+
configurable: false
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
}
|
|
66
86
|
}
|
|
67
87
|
}
|
|
68
88
|
|
|
@@ -101,6 +101,26 @@ function transformApiForProxy (context, currentInject) {
|
|
|
101
101
|
}
|
|
102
102
|
})
|
|
103
103
|
}
|
|
104
|
+
if (currentInject.moduleId) {
|
|
105
|
+
Object.defineProperties(context, {
|
|
106
|
+
__moduleId: {
|
|
107
|
+
get () {
|
|
108
|
+
return currentInject.moduleId
|
|
109
|
+
},
|
|
110
|
+
configurable: false
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
if (currentInject.dynamic) {
|
|
115
|
+
Object.defineProperties(context, {
|
|
116
|
+
__dynamic: {
|
|
117
|
+
get () {
|
|
118
|
+
return currentInject.dynamic
|
|
119
|
+
},
|
|
120
|
+
configurable: false
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
}
|
|
104
124
|
}
|
|
105
125
|
}
|
|
106
126
|
|
package/src/vuePlugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { walkChildren, parseSelector, error, hasOwn } from '@mpxjs/utils'
|
|
1
|
+
import { walkChildren, parseSelector, error, hasOwn, collectDataset } from '@mpxjs/utils'
|
|
2
2
|
import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
|
|
3
3
|
import { EffectScope } from 'vue'
|
|
4
4
|
import { PausedState } from './helper/const'
|
|
@@ -55,22 +55,25 @@ const hackEffectScope = () => {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
export default function install (Vue) {
|
|
59
|
+
Object.defineProperties(Vue.prototype, {
|
|
60
|
+
data: {
|
|
61
|
+
get () {
|
|
62
|
+
return Object.assign({}, this.$props, this.$data)
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
dataset: {
|
|
66
|
+
get () {
|
|
67
|
+
return collectDataset(this.$attrs, true)
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
id: {
|
|
71
|
+
get () {
|
|
72
|
+
return this.$attrs.id || ''
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
|
-
}
|
|
70
|
-
return dataset
|
|
71
|
-
}
|
|
75
|
+
})
|
|
72
76
|
|
|
73
|
-
export default function install (Vue) {
|
|
74
77
|
Vue.prototype.triggerEvent = function (eventName, eventDetail) {
|
|
75
78
|
// 输出Web时自定义组件绑定click事件会和web原生事件冲突,组件内部triggerEvent时会导致事件执行两次,将click事件改为_click来规避此问题
|
|
76
79
|
const escapeEvents = ['click']
|
|
@@ -78,8 +81,8 @@ export default function install (Vue) {
|
|
|
78
81
|
eventName = '_' + eventName
|
|
79
82
|
}
|
|
80
83
|
let eventObj = {}
|
|
81
|
-
const dataset =
|
|
82
|
-
const id = this
|
|
84
|
+
const dataset = this.dataset
|
|
85
|
+
const id = this.id
|
|
83
86
|
const timeStamp = +new Date()
|
|
84
87
|
eventObj = {
|
|
85
88
|
type: eventName,
|