@dolphinweex/weex-harmony 0.1.53 → 0.1.55

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dolphinweex/weex-harmony",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "description": "weex harmony adapter",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -38,6 +38,10 @@ props: {
38
38
  harmonyStyle: {
39
39
  type: Object,
40
40
  required: false,
41
+ },
42
+ onMessage: {
43
+ type: Function,
44
+ default: () => {}
41
45
  }
42
46
  },
43
47
 
@@ -68,23 +72,17 @@ mounted() {
68
72
  that.onMessage(event.data)
69
73
  }
70
74
  });
71
-
72
- this.$refs["iframe"].addEventListener('load', this.onPageFinish);
73
-
74
- this.$refs["error"].addEventListener('load', this.onError);
75
75
  },
76
76
  methods: {
77
77
  postMessage(message){
78
- const iframe = this.$refs["iframe"]
79
- const target = new URL(iframe.src).origin
80
- iframe.contentWindow.postMessage(message, target)
78
+ // const iframe = this.$refs["iframe"]
79
+ // const target = new URL(iframe.src).origin
80
+ // iframe.contentWindow.postMessage(message, target)
81
81
  //this.$refs["iframe"].contentWindow.postMessage(message, this.src)
82
82
  },
83
83
  // 自定义拓展其它逻辑
84
84
  onPageFinish(res) {
85
85
  console.log("[web] pagefinish ", res);
86
- this.$refs["iframe"].contentWindow.$midea_harmony_native = window.$midea_harmony_native
87
- this.$refs["iframe"].contentWindow.postMessage(JSON.stringify(window.$midea_harmony_native), '*');
88
86
  this.$emit("pagefinish", res);
89
87
  },
90
88
  onPageStart(res) {
@@ -27,7 +27,7 @@ export default {
27
27
  },
28
28
  autoplay: {
29
29
  type: Boolean,
30
- default: true,
30
+ default: false,
31
31
  },
32
32
  src: {
33
33
  type: String,
@@ -22,10 +22,12 @@ const componentMap = require("./index")
22
22
 
23
23
  const componentSet = new Set()
24
24
  const vBindMap = new Map()
25
+ // v-for 场景下,将 v-bind 转为方法调用所需的方法映射
26
+ const vBindMethodMap = new Map()
25
27
 
26
28
  /**
27
29
  * 判断是否为windows环境
28
- * @returns
30
+ * @returns
29
31
  */
30
32
  function isWin32(){
31
33
  if(process.platform === 'win32') {
@@ -68,52 +70,67 @@ function hasTargetElement(tagName) {
68
70
  * @param {*} node html节点
69
71
  */
70
72
  function traverseNode(node, parent = null) {
71
- if (node.type === 'element') {
73
+ if (node.type === 'element') {
72
74
  const { hasElement, componentName } = hasTargetElement(node.tagName);
73
75
  if (hasElement) {
74
76
  componentSet.add(componentName);
75
77
  }
76
78
 
77
- // 判断父节点是否有 v-for,若父节点是 <template> 且有 v-for,则跳过
78
- const isInsideVFor = parent && parent.attributes && parent.attributes.some(attr => attr.key === 'v-for');
79
-
80
- if (!isInsideVFor) { // 如果不在 v-for 中,才处理 v-bind
81
- if (node.attributes) {
82
- node.attributes.forEach((attr, index) => {
83
- if (attr.key === 'v-bind') {
84
- // 如果是对象绑定,处理 style 属性
85
- if (attr.value.trim().startsWith('{') && attr.value.trim().endsWith('}')) {
79
+ // 判断当前或父节点是否处于 v-for 场景
80
+ const hasVForInParent = parent && parent.attributes && parent.attributes.some(attr => attr.key === 'v-for')
81
+ const hasVForInCurrent = node.attributes && node.attributes.some(attr => attr.key === 'v-for')
82
+ const isInsideVFor = hasVForInParent || hasVForInCurrent
83
+
84
+ if (node.attributes) {
85
+ node.attributes.forEach((attr, index) => {
86
+ if (attr.key === 'v-bind') {
87
+ if (isInsideVFor) {
88
+ // v-for 场景:将 v-bind="expr" 转为 v-bind="customVBindMethodX(expr)"
89
+ const methodName = `customVBindMethod${index}`;
90
+ const argExpression = (attr.value || '').trim() || 'arg';
91
+ const paramName = 'arg';
92
+ if (!vBindMethodMap.has(methodName)) {
93
+ vBindMethodMap.set(methodName, { paramName });
94
+ }
95
+ // 更新模板中的属性为方法调用
96
+ node.attributes[index].value = `${methodName}(${argExpression})`;
97
+ } else {
98
+ if (
99
+ attr.value.trim().startsWith('{') &&
100
+ attr.value.trim().endsWith('}')
101
+ ) {
86
102
  const parsedAst = parser.parseExpression(attr.value);
87
- const styleProperty = parsedAst.properties.find(prop => prop.key && prop.key.name === 'style');
103
+ const styleProperty = parsedAst.properties.find(
104
+ (prop) => prop.key && prop.key.name === 'style'
105
+ );
88
106
  if (styleProperty) {
89
107
  const styleValue = styleProperty.value;
90
-
91
108
  // style 的值套上 _px2rem 方法
92
109
  styleProperty.value = {
93
110
  type: 'CallExpression',
94
111
  callee: {
95
112
  type: 'Identifier',
96
- name: '_px2rem'
113
+ name: '_px2rem',
97
114
  },
98
- arguments: [styleValue] // 将原始的 style 对象作为参数传递给 _px2rem
115
+ arguments: [styleValue], // 将原始的 style 对象作为参数传递给 _px2rem
99
116
  };
100
117
  }
101
118
  node.attributes[index] = {
102
119
  key: 'v-bind',
103
- value: generator(parsedAst).code
120
+ value: generator(parsedAst).code,
104
121
  };
105
122
  } else {
106
123
  const customComputedName = `customVBindComputed${index}`; // 自定义的名字
107
124
  vBindMap.set(customComputedName, {
108
125
  computedName: attr.value,
109
- customComputedName
126
+ customComputedName,
110
127
  });
111
128
  // 更新属性值为自定义名字
112
129
  node.attributes[index].value = customComputedName;
113
130
  }
114
131
  }
115
- });
116
- }
132
+ }
133
+ });
117
134
  }
118
135
 
119
136
  // 继续递归处理子节点
@@ -200,7 +217,7 @@ function createComputedProperty(vBindValue, computedName) {
200
217
  t.memberExpression(t.thisExpression(), t.identifier(vBindValue)),
201
218
  t.identifier('style') // this.scrollerWrapProps.style
202
219
  ),
203
- t.callExpression(
220
+ t.callExpression(
204
221
  t.identifier('this._px2rem'), // weex._px2remFn 函数
205
222
  [//函数传参
206
223
  t.memberExpression(
@@ -213,13 +230,19 @@ function createComputedProperty(vBindValue, computedName) {
213
230
  )
214
231
  ]),
215
232
  ),
216
- t.returnStatement( //return
217
- t.memberExpression(t.thisExpression(), t.identifier(vBindValue)) // this.scrollerWrapProps
233
+ t.returnStatement( // 返回浅拷贝新对象,确保引用变化以触发依赖更新
234
+ t.callExpression(
235
+ t.memberExpression(t.identifier('Object'), t.identifier('assign')),
236
+ [
237
+ t.objectExpression([]),
238
+ t.memberExpression(t.thisExpression(), t.identifier(vBindValue))
239
+ ]
240
+ )
218
241
  )
219
242
  ])
220
- )
221
243
  )
222
- ])
244
+ )
245
+ ])
223
246
  );
224
247
  }
225
248
 
@@ -233,7 +256,7 @@ function getAbsPath(address){
233
256
  const componentAbsolute = path.resolve(__dirname, address)
234
257
  if(isWin32()) {
235
258
  return path.relative(currentModulePath, componentAbsolute).replace('..\\','').replace(/\\/g,'/')
236
- } else {
259
+ } else {
237
260
  return path.relative(currentModulePath, componentAbsolute).replace('../','')
238
261
  }
239
262
  }
@@ -256,7 +279,7 @@ function generateCode(moduleResoveRet) {
256
279
  Object.keys(moduleResoveRet.styles[i].attrs).forEach((item) => {
257
280
  if (typeof moduleResoveRet.styles[i].attrs[item] === 'boolean') {
258
281
  styleAttrs += ` ${item}`
259
- } else {
282
+ } else {
260
283
  styleAttrs += ` ${item}="${moduleResoveRet.styles[i].attrs[item]}"`
261
284
  }
262
285
  })
@@ -266,7 +289,7 @@ function generateCode(moduleResoveRet) {
266
289
  Object.keys(moduleResoveRet.script.attrs).forEach((item) => {
267
290
  if (typeof moduleResoveRet.script.attrs[item] === 'boolean') {
268
291
  scriptAttrs += ` ${item}`
269
- } else {
292
+ } else {
270
293
  scriptAttrs += ` ${item}="${moduleResoveRet.script.attrs[item]}"`
271
294
  }
272
295
  })
@@ -333,6 +356,92 @@ function addComputedPropertyToScript(scriptAst, vBindMap) {
333
356
  });
334
357
  });
335
358
  }
359
+ // v-for: 注入 v-bind 方法(接收循环项,px2rem,返回新对象)
360
+ /**
361
+ * v-for 场景专用:将模板中的 v-bind="expr" 改写为 v-bind="method(expr)"
362
+ * - methodName: 注入到 methods 的方法名
363
+ * - paramName: 方法形参名(通常对应 v-for 的循环项,如 item)
364
+ * 处理目标:
365
+ * 1) 若参数存在且包含 style 字段,则对 style 执行 this._px2rem 单位转换(px → rem)
366
+ * 2) 返回一个全新的浅拷贝对象,保证引用变化,便于触发响应式更新
367
+ */
368
+ function createVBindMethod(methodName, paramName) {
369
+ return t.objectMethod(
370
+ 'method',
371
+ t.identifier(methodName),
372
+ [t.identifier(paramName)],
373
+ t.blockStatement([
374
+ t.ifStatement(
375
+ t.logicalExpression(
376
+ '&&',
377
+ t.identifier(paramName),
378
+ t.memberExpression(t.identifier(paramName), t.identifier('style'))
379
+ ),
380
+ // 1) 如果入参存在且包含 style,先做 px → rem 转换
381
+ t.blockStatement([
382
+ t.expressionStatement(
383
+ t.assignmentExpression(
384
+ '=',
385
+ t.memberExpression(t.identifier(paramName), t.identifier('style')),
386
+ t.callExpression(
387
+ t.memberExpression(t.thisExpression(), t.identifier('_px2rem')),
388
+ [t.memberExpression(t.identifier(paramName), t.identifier('style'))]
389
+ )
390
+ )
391
+ )
392
+ ])
393
+ ),
394
+ // 2) 返回一个新对象(浅拷贝)以改变引用地址,便于触发依赖更新
395
+ t.returnStatement(
396
+ t.callExpression(
397
+ t.memberExpression(t.identifier('Object'), t.identifier('assign')),
398
+ [t.objectExpression([]), t.identifier(paramName)]
399
+ )
400
+ )
401
+ ])
402
+ )
403
+ }
404
+
405
+ function addVBindMethodsToScript(scriptAst, vBindMethodMap) {
406
+ if (vBindMethodMap.size === 0) return
407
+
408
+ function ensureMethodsAndInsert(properties, methodNodes) {
409
+ let methodsNode = properties.find(p => p.key && p.key.name === 'methods')
410
+ if (!methodsNode) {
411
+ methodsNode = t.objectProperty(t.identifier('methods'), t.objectExpression([]))
412
+ properties.push(methodsNode)
413
+ }
414
+ methodNodes.forEach(node => {
415
+ const exists = methodsNode.value.properties.find(p => p.key && p.key.name === node.key.name)
416
+ if (!exists) methodsNode.value.properties.push(node)
417
+ })
418
+ }
419
+
420
+ const methodNodes = []
421
+ vBindMethodMap.forEach((info, name) => {
422
+ methodNodes.push(createVBindMethod(name, info.paramName || 'arg'))
423
+ })
424
+
425
+ traverse(scriptAst, {
426
+ ExportDefaultDeclaration(path) {
427
+ if (t.isObjectExpression(path.node.declaration)) {
428
+ ensureMethodsAndInsert(path.node.declaration.properties, methodNodes)
429
+ }
430
+ },
431
+ AssignmentExpression(path) {
432
+ const left = path.node.left
433
+ const right = path.node.right
434
+ if (
435
+ t.isMemberExpression(left) &&
436
+ left.object && left.object.name === 'module' &&
437
+ left.property && left.property.name === 'exports' &&
438
+ t.isObjectExpression(right)
439
+ ) {
440
+ ensureMethodsAndInsert(right.properties, methodNodes)
441
+ }
442
+ }
443
+ })
444
+ }
336
445
 
337
446
  module.exports = function (source) {
338
447
  if (process.env.ISHARMONY === 'true') {
@@ -344,8 +453,8 @@ module.exports = function (source) {
344
453
  styles
345
454
  } = moduleResoveRet
346
455
  if (!template) {
347
- return source
348
- }
456
+ return source
457
+ }
349
458
 
350
459
  const tempAst = parse(template.content)
351
460
  tempAst.forEach((node) => {
@@ -355,19 +464,19 @@ module.exports = function (source) {
355
464
  moduleResoveRet.template.content = stringify(tempAst);
356
465
 
357
466
  const scriptAst = parser.parse(script.content, {
358
- sourceType: 'module',
467
+ sourceType: 'module',
359
468
  // 在此添加需要解析的插件
360
469
  })
361
470
 
362
471
  // 单模块中引入了自定义组件 if (componentSet.size !== 0) {
363
472
  if (componentSet.size !== 0) {
364
473
  traverse(scriptAst, {
365
- Program(path) {
474
+ Program(path) {
366
475
  componentSet.forEach((componentName) => {
367
476
  path.unshiftContainer('body', buildImportDeclaration(componentName))
368
477
  })
369
- },
370
- AssignmentExpression(path) {
478
+ },
479
+ AssignmentExpression(path) {
371
480
  const left = path.node.left;
372
481
  if (
373
482
  left.type === 'MemberExpression' &&
@@ -378,9 +487,9 @@ module.exports = function (source) {
378
487
  if (t.isObjectExpression(path.node.right)) {
379
488
  const properties = path.node.right.properties
380
489
  const result = properties.find(item => item.key.name == 'components')
381
- if (result) {
490
+ if (result) {
382
491
  addComponentsProperty(result)
383
- } else {
492
+ } else {
384
493
  const componentsAst = t.objectProperty(t.identifier('components'), t.objectExpression([]))
385
494
  properties.push(componentsAst)
386
495
  addComponentsProperty(componentsAst)
@@ -388,15 +497,15 @@ module.exports = function (source) {
388
497
  }
389
498
  }
390
499
  }
391
- },
392
- ExportDefaultDeclaration(path) {
500
+ },
501
+ ExportDefaultDeclaration(path) {
393
502
  if (componentSet.size !== 0) {
394
503
  if (t.isObjectExpression(path.node.declaration)) {
395
504
  const properties = path.node.declaration.properties
396
505
  const result = properties.find(item => item.key.name == 'components')
397
506
  if (result) {
398
507
  addComponentsProperty(result)
399
- } else {
508
+ } else {
400
509
  const componentsAst = t.objectProperty(t.identifier('components'), t.objectExpression([]))
401
510
  properties.push(componentsAst)
402
511
  addComponentsProperty(componentsAst)
@@ -413,6 +522,10 @@ module.exports = function (source) {
413
522
  addComputedPropertyToScript(scriptAst, vBindMap);
414
523
  vBindMap.clear()
415
524
  }
525
+ if (vBindMethodMap.size !== 0) {
526
+ addVBindMethodsToScript(scriptAst, vBindMethodMap)
527
+ vBindMethodMap.clear()
528
+ }
416
529
 
417
530
  const {
418
531
  code