From 947050b6640cbe88a4d889fb5b06c1c2aae75c42 Mon Sep 17 00:00:00 2001 From: qiang Date: Thu, 3 Nov 2022 15:28:08 +0800 Subject: [PATCH] fix(mp): MPComponent skip deep observe --- .../packages/mp-vue/dist/mp.runtime.esm.js | 5 ++- src/platforms/mp-alipay/runtime/index.js | 3 +- .../mp-alipay/runtime/wrapper/util.js | 9 +++-- .../mp-toutiao/runtime/wrapper/util.js | 7 ++-- src/platforms/mp-weixin/runtime/index.js | 12 +++--- .../mp-weixin/runtime/wrapper/util.js | 37 +++++++++++++++++-- 6 files changed, 54 insertions(+), 19 deletions(-) diff --git a/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js b/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js index 4d2328025..e05106462 100644 --- a/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js +++ b/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js @@ -991,7 +991,8 @@ function observe (value, asRootData) { !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && - !value._isVue + !value._isVue && + !value.__v_isMPComponent ) { ob = new Observer(value); } @@ -5600,7 +5601,7 @@ function nextTick$1(vm, cb) { function clearInstance(key, value) { // 简易去除 Vue 和小程序组件实例 if (value) { - if (value._isVue || (value.$vm && value.$vm._isVue)) { + if (value._isVue || value.__v_isMPComponent) { return {} } } diff --git a/src/platforms/mp-alipay/runtime/index.js b/src/platforms/mp-alipay/runtime/index.js index 895b2857a..92ae71dea 100644 --- a/src/platforms/mp-alipay/runtime/index.js +++ b/src/platforms/mp-alipay/runtime/index.js @@ -1,10 +1,11 @@ -import { handleProps } from './wrapper/util' +import { handleProps, markMPComponent } from './wrapper/util' const MPComponent = Component function initHook (name, options) { const oldHook = options[name] options[name] = function (...args) { + markMPComponent(this) const props = this.props if (props && props['data-com-type'] === 'wx') { handleProps(this) diff --git a/src/platforms/mp-alipay/runtime/wrapper/util.js b/src/platforms/mp-alipay/runtime/wrapper/util.js index 68ec31889..f0f78e654 100644 --- a/src/platforms/mp-alipay/runtime/wrapper/util.js +++ b/src/platforms/mp-alipay/runtime/wrapper/util.js @@ -6,11 +6,14 @@ import { } from 'uni-shared' import { - handleLink as handleBaseLink + handleLink as handleBaseLink, + toSkip } from '../../../mp-weixin/runtime/wrapper/util' import deepEqual from './deep-equal' +export { markMPComponent } from '../../../mp-weixin/runtime/wrapper/util' + const customizeRE = /:/g const customize = cached((str) => { @@ -145,9 +148,9 @@ export function handleRef (ref) { const refName = ref.props['data-ref'] const refInForName = ref.props['data-ref-in-for'] if (refName) { - this.$vm.$refs[refName] = ref.$vm || ref + this.$vm.$refs[refName] = ref.$vm || toSkip(ref) } else if (refInForName) { - (this.$vm.$refs[refInForName] || (this.$vm.$refs[refInForName] = [])).push(ref.$vm || ref) + (this.$vm.$refs[refInForName] || (this.$vm.$refs[refInForName] = [])).push(ref.$vm || toSkip(ref)) } } diff --git a/src/platforms/mp-toutiao/runtime/wrapper/util.js b/src/platforms/mp-toutiao/runtime/wrapper/util.js index 6169f4313..aabc880d3 100644 --- a/src/platforms/mp-toutiao/runtime/wrapper/util.js +++ b/src/platforms/mp-toutiao/runtime/wrapper/util.js @@ -1,6 +1,7 @@ import { findVmByVueId, - initRefs as initRefsBase + initRefs as initRefsBase, + toSkip } from '../../../mp-weixin/runtime/wrapper/util' export const mocks = ['__route__', '__webviewId__', '__nodeid__', '__nodeId__'] @@ -19,7 +20,7 @@ export function initRefs (vm) { mpInstance.selectAllComponents('.vue-ref', (components) => { components.forEach(component => { const ref = component.dataset.ref - vm.$refs[ref] = component.$vm || component + vm.$refs[ref] = component.$vm || toSkip(component) }) }) mpInstance.selectAllComponents('.vue-ref-in-for', (forComponents) => { @@ -28,7 +29,7 @@ export function initRefs (vm) { if (!vm.$refs[ref]) { vm.$refs[ref] = [] } - vm.$refs[ref].push(component.$vm || component) + vm.$refs[ref].push(component.$vm || toSkip(component)) }) }) } diff --git a/src/platforms/mp-weixin/runtime/index.js b/src/platforms/mp-weixin/runtime/index.js index 4012f0b42..8f23f8b34 100644 --- a/src/platforms/mp-weixin/runtime/index.js +++ b/src/platforms/mp-weixin/runtime/index.js @@ -2,6 +2,7 @@ import { cached, camelize } from 'uni-shared' +import { markMPComponent } from './wrapper/util' const MPPage = Page const MPComponent = Component @@ -41,13 +42,10 @@ function initHook (name, options, isComponent) { isComponent && options.lifetimes && options.lifetimes[name] && (options = options.lifetimes) } const oldHook = options[name] - if (!oldHook) { - options[name] = function () { - initTriggerEvent(this) - } - } else { - options[name] = function (...args) { - initTriggerEvent(this) + options[name] = function (...args) { + markMPComponent(this) + initTriggerEvent(this) + if (oldHook) { return oldHook.apply(this, args) } } diff --git a/src/platforms/mp-weixin/runtime/wrapper/util.js b/src/platforms/mp-weixin/runtime/wrapper/util.js index 877a1e45c..25b3d4eef 100644 --- a/src/platforms/mp-weixin/runtime/wrapper/util.js +++ b/src/platforms/mp-weixin/runtime/wrapper/util.js @@ -1,3 +1,7 @@ +import { + isObject +} from 'uni-shared' + export const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'] export function findVmByVueId (vm, vuePid) { @@ -35,7 +39,7 @@ function selectAllComponents (mpInstance, selector, $refs) { const components = mpInstance.selectAllComponents(selector) || [] components.forEach(component => { const ref = component.dataset.ref - $refs[ref] = component.$vm || component + $refs[ref] = component.$vm || toSkip(component) if (__PLATFORM__ === 'mp-weixin') { if (component.dataset.vueGeneric === 'scoped') { component.selectAllComponents('.scoped-ref').forEach(scopedComponent => { @@ -78,7 +82,7 @@ export function initRefs (vm) { if (!$refs[ref]) { $refs[ref] = [] } - $refs[ref].push(component.$vm || component) + $refs[ref].push(component.$vm || toSkip(component)) }) return syncRefs(refs, $refs) } @@ -102,4 +106,31 @@ export function handleLink (event) { } vueOptions.parent = parentVm -} +} + +export function markMPComponent (component) { + // 在 Vue 中标记为小程序组件 + const IS_MP = '__v_isMPComponent' + Object.defineProperty(component, IS_MP, { + configurable: true, + enumerable: false, + value: true + }) + return component +} + +export function toSkip (obj) { + const OB = '__ob__' + const SKIP = '__v_skip' + if (isObject(obj) && Object.isExtensible(obj)) { + // 避免被 @vue/composition-api 观测 + Object.defineProperty(obj, OB, { + configurable: true, + enumerable: false, + value: { + [SKIP]: true + } + }) + } + return obj +} -- GitLab