Vue3绑定外部全局对象时data选项与reactive无响应问题咨询
原因说明
该现象不是Vue3的bug,是两个版本响应式实现机制的差异导致的:
- Vue2基于
Object.defineProperty实现响应式,将外部对象传入data时,Vue2会递归修改原对象所有属性的描述符,直接修改原对象属性就会触发Vue的响应式更新逻辑 - Vue3基于ES6 Proxy实现响应式,不管是
data选项还是reactive方法,都不会修改原对象本身,仅会返回一个包裹原对象的代理对象,只有修改代理对象才会触发响应更新,直接修改外部原对象无法被代理层感知,因此视图不会同步更新
可行解决方案
由于无法修改外部共享模块的代码,可以选用以下两种方案实现需求:
方案1:劫持外部对象属性同步(性能最优)
通过Object.defineProperty劫持外部对象的属性修改,同步更新到Vue的响应式代理对象即可,无额外性能开销:
const { createApp, reactive } = Vue const app = createApp({ setup(){ // 创建响应式代理 const share = reactive({...EXTERNAL_OBJECT}) // 劫持外部对象所有顶层属性的修改,同步到响应式对象 Object.keys(EXTERNAL_OBJECT).forEach(key => { let currentVal = EXTERNAL_OBJECT[key] Object.defineProperty(EXTERNAL_OBJECT, key, { get: () => currentVal, set: newVal => { currentVal = newVal share[key] = newVal }, configurable: true, enumerable: true }) }) // 如果有嵌套属性,递归执行上述劫持逻辑即可 return { share } } }) app.mount('#app')
方案2:定时同步(代码最简)
如果外部对象层级不深、修改频率不高,可以用轻量轮询的方式同步原对象和响应式对象的值:
const { createApp, reactive, onUnmounted } = Vue const app = createApp({ setup(){ const share = reactive({...EXTERNAL_OBJECT}) // 每100ms同步一次,间隔可根据业务场景调整 const syncTimer = setInterval(() => { Object.assign(share, EXTERNAL_OBJECT) // 嵌套属性可以替换为深合并逻辑 }, 100) // 组件销毁时清除定时器 onUnmounted(() => clearInterval(syncTimer)) return { share } } }) app.mount('#app')
内容的提问来源于stack exchange,提问作者user1517325
相关产品推荐
相关产品推荐

