Table of contents
3. Deep Responsiveness and Shallow Responsiveness
4. Reactive Proxy vs. Primitive Objects
5. Define responsive variables with ref()
1. Vue3 Responsive Basics
1. Declare reactive state
We can use the reactive() function to create a reactive object or array and if we want to use it, we can setup()
define it in the function and return it.
<script>
import { reactive } from "vue";
export default {
// `setup` 是一个专门用于组合式 API 的特殊钩子函数
setup() {
let oneNumber = reactive({ count: 0 });
function add() {
oneNumber.count++;
}
// 暴露 state 到模板
return {
oneNumber,
add,
};
},
};
</script>
<template>
<button @click="add">
{
{ oneNumber.count }}
</button>
</template>
<style scoped></style>
It is cumbersome to manually expose a large number of states and methods in setup()
functions, so we can use <script setup> to simplify the code, as follows:
<script setup>
import { reactive } from "vue";
let oneNumber = reactive({ count: 0 });
function add() {
oneNumber.count++;
}
</script>
<template>
<button @click="add">
{
{ oneNumber.count }}
</button>
</template>
2. DOM update timing
When changing the responsive state, the DOM is automatically updated. However, DOM updates are not synchronous . Instead, Vue will buffer them until the "next moment" in the update cycle to ensure that no matter how many state changes you make, each component is only updated once. To wait for a DOM update to complete after a state change, you can use this global API
<script setup>
import { reactive, nextTick } from "vue";
let oneNumber = reactive({ count: 0 });
function add() {
oneNumber.count++;
console.log(document.getElementById("addBtn").textContent);
nextTick(() => {
// 访问更新后的 DOM
console.log(document.getElementById("addBtn").textContent);
});
}
</script>
<template>
<button @click="add" id="addBtn">
{
{ oneNumber.count }}
</button>
</template>
Obviously, when executingadd时,访问dom的内容是操作count之前的值,在nextTick之后才为count更新后的值
3. Deep Responsiveness and Shallow Responsiveness
Deep Responsiveness:
In Vue, state is deep reactive by default. This means that changes can be detected even when changing deep objects or arrays.
<script setup>
import { reactive } from "vue";
let oneNumberObj = reactive({
nested: { count: 0 },
arr: ["hello", "vue3"],
});
function add() {
oneNumberObj.nested.count++;
oneNumberObj.arr[0] = "ts" + oneNumberObj.nested.count;
}
</script>
<template>
<button @click="add" id="addBtn">
{
{ oneNumberObj.nested.count }}--{
{ oneNumberObj.arr[0] }}
</button>
</template>
Obviously, when executingadd时,count和arr都可以做出相应
Shallow responsiveness:
Only the root-level properties in a shallow reactive object are reactive.
<script setup>
import { reactive,shallowReactive } from "vue";
let oneNumberObjShallow = shallowReactive({
nested: { count: 0 },
arr: ["hello", "vue3"],
});
function add() {
oneNumberObjShallow.nested.count++;
oneNumberObjShallow.arr[0] = "ts" + oneNumberObjShallow.nested.count;
}
</script>
<template>
<button @click="add" id="addBtn">
{
{ oneNumberObjShallow.nested.count }}--{
{ oneNumberObjShallow.arr[0] }}
</button>
</template>
Obviously, when executingadd时,count和arr不可以做出相应
4. Reactive Proxy vs. Primitive Objects
reactive()
What is returned is a Proxy of the original object, which is not equal to the original object.
Only the proxy object is reactive, changing the original object will not trigger an update. So best practice with Vue's reactive system is to only use proxy versions of your declared objects
Calling on the same original object reactive()
will always return the same proxy object, while calling on an existing proxy object reactive()
will return itself
as follows:
<script setup>
import { reactive } from "vue";
let oneNumber = { count: 0 };
let proxy = reactive(oneNumber)
function addProxy() {
proxy.count++;
console.log(proxy === oneNumber) //false
console.log(reactive(oneNumber) === proxy) //true
console.log(reactive(proxy) === proxy) //true
}
</script>
<template>
<button @click="addProxy">
{
{ proxy.count }}
</button>
</template>
5. ref()
Define responsive variables with
reactive() is only valid for object types, so we can use ref()
to allow us to create reactive types that can use any value type
ref()
Wrap the value of the incoming parameter as a .value
ref object with attributes
When refs are accessed as top-level attributes in templates, they are automatically "unwrapped", so there is no need to use .value
Unlike reactive objects, refs Map
are not unwrapped when accessed as elements of a reactive array or like this native collection type.
as follows:
<script setup>
import { ref,reactive } from 'vue'
const oneNumber = ref(0)
const oneStr = reactive([ref('Vue3')])
function add() {
oneNumber.value++
}
</script>
<template>
<button @click="add">
{
{ oneNumber }} <!-- 无需 .value -->
</button>
<div>{
{ oneStr[0].value }}</div>
</template>
If you have any questions, please comment below and I will answer them for you.