[Vue3] Responsive data_2


[Vue3] Responsive data_1



readonly & shallowReadonly

  • Format:readonly(响应性数据)
  • readonlyModified 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(响应性数据)
  • shallowReadonlyModified 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

  • reactiveChange 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

  • provideUsed to pass data to descendant components:provide("XXX", 数据值)
  • injectUsed 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 toRawDecorate 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 readonlydecorate 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

  1. isRef- checks if a value is refdecorated
  2. isReactive- checks if an object is reactivedecorated
  3. isReadonly- checks if an object is readonlydecorated
  4. isProxy- Check if an object is decorated by reactive/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>

Guess you like

Origin blog.csdn.net/Superman_H/article/details/126276553