From a61d476f7ebf0c8df19ec3a156fb00ffe28d3c8f Mon Sep 17 00:00:00 2001 From: xiaolei <1017653702@qq.com> Date: Tue, 15 Oct 2024 14:21:12 +0800 Subject: [PATCH 1/2] [feat]support rn ref for wx:for --- .../platform/builtInMixins/refsMixin.ios.js | 58 +++++-------------- .../patch/react/getDefaultOptions.ios.js | 10 ++++ .../lib/template-compiler/compiler.js | 42 +++++++++----- .../lib/template-compiler/gen-node-react.js | 8 +++ 4 files changed, 61 insertions(+), 57 deletions(-) diff --git a/packages/core/src/platform/builtInMixins/refsMixin.ios.js b/packages/core/src/platform/builtInMixins/refsMixin.ios.js index 5f92eb4047..7e54635062 100644 --- a/packages/core/src/platform/builtInMixins/refsMixin.ios.js +++ b/packages/core/src/platform/builtInMixins/refsMixin.ios.js @@ -1,59 +1,33 @@ -import { BEFORECREATE, CREATED } from '../../core/innerLifecycle' +import { BEFORECREATE } from '../../core/innerLifecycle' import { createSelectorQuery } from '@mpxjs/api-proxy' -import { computed } from '../../observer/computed' export default function getRefsMixin () { return { [BEFORECREATE] () { this.__refs = {} this.$refs = {} - }, - // __getRefs强依赖数据响应,需要在CREATED中执行 - [CREATED] () { + this.__selectorMap = {} this.__getRefs() }, methods: { __getRefs () { const refs = this.__getRefsData() || [] const target = this - this.__selectorMap = computed(() => { - const selectorMap = {} - refs.forEach(({ key, type, sKeys }) => { - // sKeys 是使用 wx:ref 没有值的标记场景,支持运行时的 createSelectorQuery 的使用 - if (sKeys) { - sKeys.forEach((item = {}) => { - const computedKey = item.key - const prefix = item.prefix - const selectors = this[computedKey] || '' - selectors.trim().split(/\s+/).forEach(item => { - const selector = prefix + item - selectorMap[selector] = selectorMap[selector] || [] - selectorMap[selector].push({ type, key }) - }) - }) - } else { - selectorMap[key] = selectorMap[key] || [] - selectorMap[key].push({ type, key }) + refs.forEach(({ key, type, all }) => { + this.__selectorMap[key] = this.__selectorMap[key] || [] + this.__selectorMap[key].push({ key, type }) + Object.defineProperty(this.$refs, key, { + enumerable: true, + configurable: true, + get () { + const refs = target.__refs[key] || [] + if (type === 'component') { + return all ? refs : refs[0] + } else { + return createSelectorQuery().in(target).select(key, all) + } } }) - return selectorMap - }) - refs.forEach(({ key, type, all, sKeys }) => { - // 如果没有 sKey 说明使用的是 wx:ref="xxx" 的场景 - if (!sKeys) { - Object.defineProperty(this.$refs, key, { - enumerable: true, - configurable: true, - get () { - const refs = target.__refs[key] || [] - if (type === 'component') { - return all ? refs : refs[0] - } else { - return createSelectorQuery().in(target).select(key, all) - } - } - }) - } }) }, __getRefVal (key) { @@ -67,7 +41,7 @@ export default function getRefsMixin () { __selectRef (selector, refType, all = false) { const splitedSelector = selector.match(/(#|\.)?[^.#]+/g) || [] const refsArr = splitedSelector.map(selector => { - const selectorMap = this.__selectorMap?.value[selector] || [] + const selectorMap = this.__selectorMap[selector] || [] const res = [] selectorMap.forEach(({ type, key }) => { if (type === refType) { diff --git a/packages/core/src/platform/patch/react/getDefaultOptions.ios.js b/packages/core/src/platform/patch/react/getDefaultOptions.ios.js index 12ad048939..64c9d3ad59 100644 --- a/packages/core/src/platform/patch/react/getDefaultOptions.ios.js +++ b/packages/core/src/platform/patch/react/getDefaultOptions.ios.js @@ -143,6 +143,16 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps } return result }, + _r (refsConf = []) { + refsConf.forEach((item = []) => { + const [key, type, prefix, selectors = ''] = item + selectors.trim().split(/\s+/).forEach(item => { + const selector = prefix + item + this.__selectorMap[selector] = this.__selectorMap[selector] || [] + this.__selectorMap[selector].push({ type, key }) + }) + }) + }, triggerEvent (eventName, eventDetail) { const props = propsRef.current const handler = props && (props['bind' + eventName] || props['catch' + eventName] || props['capture-bind' + eventName] || props['capture-catch' + eventName]) diff --git a/packages/webpack-plugin/lib/template-compiler/compiler.js b/packages/webpack-plugin/lib/template-compiler/compiler.js index 8a0b318815..0e00cf3016 100644 --- a/packages/webpack-plugin/lib/template-compiler/compiler.js +++ b/packages/webpack-plugin/lib/template-compiler/compiler.js @@ -1719,6 +1719,7 @@ function processRefReact (el, meta) { meta.refs = [] } const all = !!forScopes.length + const forIndexs = all ? forScopes.map(scope => scope.index).join('+') : null const refConf = { key: val, all, @@ -1726,34 +1727,45 @@ function processRefReact (el, meta) { } if (!val) { - refConf.key = `ref_rn_${++refId}` - refConf.sKeys = [] + refConf.key = `"ref_rn_${++refId}"${forIndexs ? '+' + forIndexs : ''}` const rawId = el.attrsMap.id const rawClass = el.attrsMap.class const rawDynamicClass = el.attrsMap[config[mode].directive.dynamicClass] - meta.computed = meta.computed || [] if (rawId) { + el.refs = el.refs || [] const staticId = parseMustacheWithContext(rawId).result - const computedIdKey = `_ri${refId}` - refConf.sKeys.push({ key: computedIdKey, prefix: '#' }) - meta.computed.push(`${computedIdKey}() {\n return ${staticId}}`) + el.refs.push({ + key: refConf.key, + type, + prefix: '#', + selectors: `${staticId}` + }) } if (rawClass || rawDynamicClass) { + el.refs = el.refs || [] const staticClass = parseMustacheWithContext(rawClass).result const dynamicClass = parseMustacheWithContext(rawDynamicClass).result - const computedClassKey = `_rc${refId}` - refConf.sKeys.push({ key: computedClassKey, prefix: '.' }) - meta.computed.push(`${computedClassKey}() {\n return this.__getClass(${staticClass}, ${dynamicClass})}`) + el.refs.push({ + key: refConf.key, + type, + prefix: '.', + selectors: `this.__getClass(${staticClass}, ${dynamicClass})` + }) } - } - meta.refs.push(refConf) + addAttrs(el, [{ + name: 'ref', + value: `{{ this.__getRefVal(${refConf.key}) }}` + }]) + } else { + meta.refs.push(refConf) - addAttrs(el, [{ - name: 'ref', - value: `{{ this.__getRefVal('${refConf.key}') }}` - }]) + addAttrs(el, [{ + name: 'ref', + value: `{{ this.__getRefVal('${refConf.key}') }}` + }]) + } } } diff --git a/packages/webpack-plugin/lib/template-compiler/gen-node-react.js b/packages/webpack-plugin/lib/template-compiler/gen-node-react.js index 8656bf153b..1d2584877a 100644 --- a/packages/webpack-plugin/lib/template-compiler/gen-node-react.js +++ b/packages/webpack-plugin/lib/template-compiler/gen-node-react.js @@ -22,6 +22,12 @@ function genFor (node) { return `_i(${node.for.exp}, function(${item},${index}){return ${genNode(node)}})` } +function genRef (node) { + node.refProcessed = true + const refs = node.refs.map(item => `[${item.key}, "${item.type}", "${item.prefix}", ${item.selectors}]`) + return `_r([${refs}]), ` + genNode(node) +} + const s = JSON.stringify function mapAttrName (name) { @@ -48,6 +54,8 @@ function genNode (node) { exp += genFor(node) } else if (node.if && !node.ifProcessed) { exp += genIf(node) + } else if (node.refs && !node.refProcessed) { + exp += genRef(node) } else { const attrExpMap = (node.exps || []).reduce((map, { exp, attrName }) => { if (attrName) { From ae7993ee878e06e407f0ab0374852f662346aa01 Mon Sep 17 00:00:00 2001 From: xiaolei <1017653702@qq.com> Date: Wed, 16 Oct 2024 16:13:29 +0800 Subject: [PATCH 2/2] [update]optimize refConf for render function --- .../platform/builtInMixins/refsMixin.ios.js | 27 +++++++------ .../patch/react/getDefaultOptions.ios.js | 10 ----- .../lib/template-compiler/compiler.js | 39 +++++++------------ .../lib/template-compiler/gen-node-react.js | 8 ---- 4 files changed, 28 insertions(+), 56 deletions(-) diff --git a/packages/core/src/platform/builtInMixins/refsMixin.ios.js b/packages/core/src/platform/builtInMixins/refsMixin.ios.js index 7e54635062..26ce17f6f9 100644 --- a/packages/core/src/platform/builtInMixins/refsMixin.ios.js +++ b/packages/core/src/platform/builtInMixins/refsMixin.ios.js @@ -6,7 +6,6 @@ export default function getRefsMixin () { [BEFORECREATE] () { this.__refs = {} this.$refs = {} - this.__selectorMap = {} this.__getRefs() }, methods: { @@ -14,15 +13,12 @@ export default function getRefsMixin () { const refs = this.__getRefsData() || [] const target = this refs.forEach(({ key, type, all }) => { - this.__selectorMap[key] = this.__selectorMap[key] || [] - this.__selectorMap[key].push({ key, type }) Object.defineProperty(this.$refs, key, { enumerable: true, configurable: true, get () { - const refs = target.__refs[key] || [] if (type === 'component') { - return all ? refs : refs[0] + return all ? target.selectAllComponents(key) : target.selectComponent(key) } else { return createSelectorQuery().in(target).select(key, all) } @@ -30,23 +26,30 @@ export default function getRefsMixin () { }) }) }, - __getRefVal (key) { + __getRefVal (type, selectorsConf) { return (instance) => { if (instance) { - this.__refs[key] = this.__refs[key] || [] - this.__refs[key].push(instance) + selectorsConf.forEach((item = []) => { + const [prefix, selectors = ''] = item + if (selectors) { + selectors.trim().split(/\s+/).forEach(selector => { + const refKey = prefix + selector + this.__refs[refKey] = this.__refs[refKey] || [] + this.__refs[refKey].push({ type, instance }) + }) + } + }) } } }, __selectRef (selector, refType, all = false) { const splitedSelector = selector.match(/(#|\.)?[^.#]+/g) || [] const refsArr = splitedSelector.map(selector => { - const selectorMap = this.__selectorMap[selector] || [] + const refs = this.__refs[selector] || [] const res = [] - selectorMap.forEach(({ type, key }) => { + refs.forEach(({ type, instance }) => { if (type === refType) { - const _refs = this.__refs[key] || [] - res.push(..._refs) + res.push(instance) } }) return res diff --git a/packages/core/src/platform/patch/react/getDefaultOptions.ios.js b/packages/core/src/platform/patch/react/getDefaultOptions.ios.js index 64c9d3ad59..12ad048939 100644 --- a/packages/core/src/platform/patch/react/getDefaultOptions.ios.js +++ b/packages/core/src/platform/patch/react/getDefaultOptions.ios.js @@ -143,16 +143,6 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps } return result }, - _r (refsConf = []) { - refsConf.forEach((item = []) => { - const [key, type, prefix, selectors = ''] = item - selectors.trim().split(/\s+/).forEach(item => { - const selector = prefix + item - this.__selectorMap[selector] = this.__selectorMap[selector] || [] - this.__selectorMap[selector].push({ type, key }) - }) - }) - }, triggerEvent (eventName, eventDetail) { const props = propsRef.current const handler = props && (props['bind' + eventName] || props['catch' + eventName] || props['capture-bind' + eventName] || props['capture-catch' + eventName]) diff --git a/packages/webpack-plugin/lib/template-compiler/compiler.js b/packages/webpack-plugin/lib/template-compiler/compiler.js index 0e00cf3016..bf45a8b90c 100644 --- a/packages/webpack-plugin/lib/template-compiler/compiler.js +++ b/packages/webpack-plugin/lib/template-compiler/compiler.js @@ -1719,53 +1719,40 @@ function processRefReact (el, meta) { meta.refs = [] } const all = !!forScopes.length - const forIndexs = all ? forScopes.map(scope => scope.index).join('+') : null const refConf = { key: val, all, type } + const selectors = [] + + /** + * selectorsConf: [type, [[prefix, selector], [prefix, selector]]] + */ if (!val) { - refConf.key = `"ref_rn_${++refId}"${forIndexs ? '+' + forIndexs : ''}` const rawId = el.attrsMap.id const rawClass = el.attrsMap.class const rawDynamicClass = el.attrsMap[config[mode].directive.dynamicClass] if (rawId) { - el.refs = el.refs || [] const staticId = parseMustacheWithContext(rawId).result - el.refs.push({ - key: refConf.key, - type, - prefix: '#', - selectors: `${staticId}` - }) + selectors.push({ prefix: '#', selector: `${staticId}` }) } if (rawClass || rawDynamicClass) { - el.refs = el.refs || [] const staticClass = parseMustacheWithContext(rawClass).result const dynamicClass = parseMustacheWithContext(rawDynamicClass).result - el.refs.push({ - key: refConf.key, - type, - prefix: '.', - selectors: `this.__getClass(${staticClass}, ${dynamicClass})` - }) + selectors.push({ prefix: '.', selector: `this.__getClass(${staticClass}, ${dynamicClass})` }) } - - addAttrs(el, [{ - name: 'ref', - value: `{{ this.__getRefVal(${refConf.key}) }}` - }]) } else { meta.refs.push(refConf) - - addAttrs(el, [{ - name: 'ref', - value: `{{ this.__getRefVal('${refConf.key}') }}` - }]) + selectors.push({ prefix: '', selector: `"${refConf.key}"` }) } + const selectorsConf = selectors.map(item => `["${item.prefix}", ${item.selector}]`) + addAttrs(el, [{ + name: 'ref', + value: `{{ this.__getRefVal('${type}', [${selectorsConf}]) }}` + }]) } } diff --git a/packages/webpack-plugin/lib/template-compiler/gen-node-react.js b/packages/webpack-plugin/lib/template-compiler/gen-node-react.js index 1d2584877a..8656bf153b 100644 --- a/packages/webpack-plugin/lib/template-compiler/gen-node-react.js +++ b/packages/webpack-plugin/lib/template-compiler/gen-node-react.js @@ -22,12 +22,6 @@ function genFor (node) { return `_i(${node.for.exp}, function(${item},${index}){return ${genNode(node)}})` } -function genRef (node) { - node.refProcessed = true - const refs = node.refs.map(item => `[${item.key}, "${item.type}", "${item.prefix}", ${item.selectors}]`) - return `_r([${refs}]), ` + genNode(node) -} - const s = JSON.stringify function mapAttrName (name) { @@ -54,8 +48,6 @@ function genNode (node) { exp += genFor(node) } else if (node.if && !node.ifProcessed) { exp += genIf(node) - } else if (node.refs && !node.refProcessed) { - exp += genRef(node) } else { const attrExpMap = (node.exps || []).reduce((map, { exp, attrName }) => { if (attrName) {