在 Vue 3 中使用响应式的原语反应性
根据文档,使用 reactive
包装器时,原语不应该变得反应性,这就是为什么在这种情况下我们应该使用 ref
。同样的情况是当我们想要重新分配整个对象而不是改变它时。
我的问题是,为什么在以下代码段中,当我们取消注释行时, counter2
和 state2.counter
开始正常工作?
<script setup>
import { ref, reactive } from 'vue';
let counter1 = ref(0);
let counter2 = reactive(0);
const increment = () => {
// counter1.value++;
counter2++;
}
</script>
<template>
<h3>counter1 {{ counter1 }}</h3>
<h3>counter2 {{ counter2 }}</h3>
<button @click="increment">increment</button>
</template>
游乐场:链接
<script setup>
import { ref, reactive } from 'vue';
let state1 = ref({ counter: 0 });
let state2 = reactive({ counter: 0 });
const increment = () => {
// state1.value = { counter: state1.value.counter + 1 };
state2 = { counter: state2.counter + 1 };
}
</script>
<template>
<h3>counter1 {{ state1.counter }}</h3>
<h3>counter2 {{ state2.counter }}</h3>
<button @click="increment">increment</button>
</template>
游乐场:链接
According to the docs, primitives shouldn't become reactive when using reactive
wrapper, that's why in this case we should go with ref
. The same situation is when we want to reassign the entire object instead of mutating it.
My question is why in the following snippets counter2
and state2.counter
start working correctly when we uncomment the commented lines?
<script setup>
import { ref, reactive } from 'vue';
let counter1 = ref(0);
let counter2 = reactive(0);
const increment = () => {
// counter1.value++;
counter2++;
}
</script>
<template>
<h3>counter1 {{ counter1 }}</h3>
<h3>counter2 {{ counter2 }}</h3>
<button @click="increment">increment</button>
</template>
Playground: link
<script setup>
import { ref, reactive } from 'vue';
let state1 = ref({ counter: 0 });
let state2 = reactive({ counter: 0 });
const increment = () => {
// state1.value = { counter: state1.value.counter + 1 };
state2 = { counter: state2.counter + 1 };
}
</script>
<template>
<h3>counter1 {{ state1.counter }}</h3>
<h3>counter2 {{ state2.counter }}</h3>
<button @click="increment">increment</button>
</template>
Playground: link
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Vue 检测到
counter1
的突变并重新渲染整个组件,其中包括更新的counter2
值。由于counter1
更改导致重新渲染,您会看到更新后的counter2
值。单独改变counter2
不会触发渲染,因为它不是反应性的。Vue detects the mutation to
counter1
and re-renders the entire component which includes the updatedcounter2
value. You're seeing the updatedcounter2
value due to the re-render caused by the change tocounter1
. Mutatingcounter2
alone will not trigger a render because it isn't reactive.您应该坚持使用 ref 来拥有反应类型,甚至指定它,因为仅仅为计数器创建一个对象是没有意义的。您可以使用 const counter = ref(0) 当您在内部处理 value 时,您不必使用 let,并且在脚本中访问时只需使用 counter.value 并在 HTML <代码>{{计数器}}。使用 ref 您可以创建一个反应式原始值,同时通过使用反应式用于创建反应式对象并作为数据的替代品。因此,只需使用 ref 即可,因为它几乎可以用于所有内容,您甚至可以创建自己的类型并指定它们。另外,当使用反应式时,你不能交换完整的对象,并且它不能用于所有东西,另一方面 ref 唯一的缺点是 .value ,这可能很烦人,但最终,这是值得的。
You should stick with ref to have a reactive type and even specify it as it is pointless to make an object just for the counter. You can use
const counter = ref<int>(0)
as you work with value inside you don't have to use let and when accessing in the script just use counter.value and in you HTML{{ counter }}
. With ref you create a reactive primitive value meanwhile by using reactive is used for creating reactive objects and it's as a replacement for data. So just use ref as it can be used for almost everything you can even create your own types and specify them. Also when working with reactive you can't swap the complete object and it can't be used for everything on the other hand ref can only downside is .value which can be annoying but in the end, it's worth it.