vue3 reactive() 的局限性:对解构操作不友好,ref似乎也有这个问题?
https://cn.vuejs.org/guide/essentials/reactivity-fundamentals...
https://play.vuejs.org/#eNp9UcFuwjAM/ZUoF4qoShE3VJC2iQM7bNO2Y...
如代码所示,解构丢失响应性连接似乎并不只是reactive的“局限性”
回答:
因为截至目前, JS 无法监听变量的赋值行为,不管是 Object.defineProperties
还是 Proxy
,其实都是拦截对象的属性变化,而不是监听变量的赋值。
const a = 0;let b = 1;
var c = 2;
?这里的a
、b
、c
都是“变量”,对它们的赋值,是无法监听的。
let obj = { a: 0,
b: 1
}
let { a } = obj;
?这里的obj.a
、obj.b
都是“对象的属性”,对这些属性的赋值行为可以通过Proxy
或者Object.defineProperties
拦截到。
但是对obj
本身重新赋值的行为,是无法被监听的,同理,对从obj
中解构出来并重新命名为a
的变量的赋值,也无法被监听。
其实也正是因为变量赋值无法被监听,Vue3 才搞出 ref
这个东西来,把基础类型包装进一个对象里,就可以对这个对象的属性.value
进行监听了。
不过 JS 不能监听,不代表无法实现这样的语义,有一个比较年轻的 Svelte 框架,通过预编译,对用户屏蔽类似的包装过程,所以如果是使用 Svelte 的话,延时器回调中对变量赋值,可以直接反映到视图上:
<script> let x = 0;
const interval = setInterval(() => {
x++;
x >= 100 && clearInterval(interval);
}, 1e3);
</script>
<h1>Hello world!{x}</h1>
但是 Vue 目前不允许这样写。
其实 Vue 有过一个提案,用 JS 的 label 语句来代替 ref
函数:
ref:count = 0;count++
但是由于这个提案给 label 语句带来了歧义,在 Vue 社区和开发者群体中引起了强烈的反对,因此只得作罢,所以时至今日, Vue 的响应式还是以监听对象属性的方式来完成,对解构而来的变量重新赋值不会被监听。
回答:
reactive()
的话可用利用 toRefs()
方法转换为 ref 变量构成的对象从而使用结构赋值,参见 https://vuejs.org/api/reactivity-utilities.html#torefs 以及官方的示例
const state = reactive({ foo: 1,
bar: 2
})
const { foo, bar } = toRefs(state)
// The ref and the original property is "linked"
state.foo++
console.log(foo.value) // 2
foo.value++
console.log(state.foo) // 3
以上是 vue3 reactive() 的局限性:对解构操作不友好,ref似乎也有这个问题? 的全部内容, 来源链接: utcz.com/p/935156.html