[Vue3] Responsive data_1
readonly
& shallowReadonly
- Format:
readonly(响应性数据)
readonly
Modified data, cannot be modified
<template>
<p>obj.name: {
{ obj.name }}</p>
<button @click="obj.name += '!'">修改 obj.name</button>
<hr />
<p>reObj.name: {
{ reObj.name }}</p>
<!-- 点击不会被修改,控制台会抛出警告 -->
<button @click="reObj.name += '!'">修改 reObj.name</button>
</template>
<script>
import {
reactive, readonly } from "vue";
export default {
name: "App",
setup() {
let obj = reactive({
name: "superman" });
let reObj = readonly(obj);
return {
obj, reObj };
},
};
</script>
shallowReadonly
- Format:
shallowReadonly(响应性数据)
shallowReadonly
Modified data, shallow data cannot be modified, but deep data can be modified
<template>
<!-- 浅层数据 -->
<p>obj.name: {
{ obj.name }}</p>
<button @click="obj.name += '!'">修改 obj.name</button>
<p>reObj.name: {
{ reObj.name }}</p>
<!-- 点击不会被修改,控制台会抛出警告 -->
<button @click="reObj.name += '!'">修改 reObj.name</button>
<hr />
<!-- 深层数据 -->
<p>obj.girlfriend.name: {
{ obj.girlfriend.name }}</p>
<button @click="obj.girlfriend.name += '!'">
修改 obj.girlfriend.name
</button>
<p>reObj.girlfriend.name: {
{ reObj.girlfriend.name }}</p>
<!-- 点击可以修改 -->
<button @click="reObj.girlfriend.name += '!'">
修改 reObj.girlfriend.name
</button>
</template>
<script>
import {
reactive, shallowReadonly } from "@vue/reactivity";
export default {
name: "App",
setup() {
let obj = reactive({
name: "superman",
girlfriend: {
name: "superwoman" },
});
let reObj = shallowReadonly(obj);
return {
obj, reObj };
},
};
</script>
toRaw
&markRaw
reactive
Change the modified responsive data to normal data:toRaw(响应式数据)
- Usage scenario: used to read the common object corresponding to the responsive object, all operations on this common object will not cause the page to be updated
<template>
<p>obj.name: {
{ obj.name }}</p>
<button @click="obj.name += '!'">修改 obj.name</button>
<hr />
<p>raObj.name: {
{ raObj.name }}</p>
<button @click="raObj.name += '!'">修改 raObj.name</button>
</template>
<script>
import {
reactive, toRaw } from "@vue/reactivity";
export default {
name: "App",
setup() {
let obj = reactive({
name: "superman" });
let raObj = toRaw(obj);
return {
obj, raObj };
},
};
</script>
It can be found that the data modified by toRaw will become normal data, modify the normal data, the page will not be re-rendered
but the data has been changed, if the page is re-rendered, the latest data will still be displayed
markRaw
- Used to mark an object data so that it can never be a reactive data
<template>
<p>obj: {
{ obj }}</p>
<p>
第一步: 选择接收数据
<button @click="changeObj">changeObj</button> |
<button @click="maChangeObj">maChangeObj</button>
</p>
<p>
第二步: 选择改变的数据
<button @click="changeName">changeName</button> |
<button @click="changeGirl">changeGirl</button>
</p>
</template>
<script>
import {
markRaw, reactive } from "vue";
export default {
name: "App",
setup() {
// 定义响应式数据
let obj = reactive({
name: "superman" });
// 假设通过 Ajax 接收一个对象数据
function changeObj() {
let girl = {
name: "superwoman" };
obj.girlfriend = girl;
}
// 假设通过 Ajax 接收一个对象数据,并用 markRaw 修饰
function maChangeObj() {
let girl = markRaw({
name: "superwoman" });
obj.girlfriend = girl;
}
// 改变接收的数据
function changeGirl() {
obj.girlfriend.name += "!" }
// 改变原数据
function changeName() {
obj.name += "!" }
return {
obj,
changeObj,
changeGirl,
maChangeObj,
changeName,
};
},
};
</script>
It can be found that the normally received object data can be modified and rendered to the page;
however, the object data modified with markRaw will be modified but not rendered to the page (of course, when the page is re-rendered, will still show the latest data)
provide
&inject
provide
Used to pass data to descendant components:provide("XXX", 数据值)
inject
Used to receive data passed by ancestor components:inject("XXX")
<template>
<p>App: {
{ obj }}</p>
<button @click="obj.name += '!'">修改数据 obj.name</button>
<hr />
<Son />
</template>
<script>
import { provide, reactive } from "vue";
import Son from "./components/Son.vue";
export default {
name: "App",
components: { Son },
setup() {
let obj = reactive({ name: "superman" });
provide("myObj", obj); // 传递数据
return { obj };
},
};
</script>
<template>
<p>Son: {
{ msg }}</p>
<button @click="msg.name += '!'">修改数据</button>
</template>
<script>
import { inject } from "vue";
export default {
name: "Son",
setup() {
let msg = inject("myObj"); // 接收数据
return { msg };
},
};
</script>
At this point, no matter which component modifies the data, the data will be modified successfully and rendered to the page
-
If you want descendant components to not be able to modify and render data, you can use
toRaw
Decorate data:At this point, descendant components cannot modify and render the received data, but the data has already been modified. If the page is re-rendered, the latest data will still be displayed
<template>
<p>App: {
{ obj }}</p>
<button @click="obj.name += '!'">修改数据 obj.name</button>
<hr />
<Son />
</template>
<script>
import { provide, reactive, toRaw } from "vue";
import Son from "./components/Son.vue";
export default {
name: "App",
components: { Son },
setup() {
let obj = reactive({ name: "superman" });
let rawObj = toRaw(obj); // 将 reactive 修饰的响应式数据变为普通数据
provide("myObj", rawObj); // 传递数据
return { obj };
},
};
</script>
-
If modifying data is not allowed, you can use
readonly
decorate data:At this time, only the parent component can modify the data, and the descendant components cannot modify the received data
<template>
<p>App: {
{ obj }}</p>
<button @click="obj.name += '!'">修改数据 obj.name</button>
<hr />
<Son />
</template>
<script>
import { provide, reactive, readonly } from "vue";
import Son from "./components/Son.vue";
export default {
name: "App",
components: { Son },
setup() {
let obj = reactive({ name: "superman" });
let readObj = readonly(obj); // readonly 修饰的数据,不可被修改
provide("myObj", readObj); // 传递数据
return { obj };
},
};
</script>
Judging Responsive Data
isRef
- checks if a value isref
decoratedisReactive
- checks if an object isreactive
decoratedisReadonly
- checks if an object isreadonly
decoratedisProxy
- Check if an object is decorated byreactive
/readonly
<script>
import {
isProxy, isReactive, isReadonly, isRef, reactive, readonly, ref } from 'vue';
export default {
name: "App",
setup() {
let person = reactive({
name: "superman" });
let num = ref(0);
let readonly_num = readonly(num);
console.log(isReactive(person)); // true
console.log(isRef(num)); // true
console.log(isReadonly(readonly_num)); // true
console.log(isProxy(readonly_num)); // true
},
};
</script>