【Vue3】响应性数据_2


【Vue3】响应性数据_1



readonly & shallowReadonly

  • 格式:readonly(响应性数据)
  • readonly 修饰的数据,不可被修改
<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

  • 格式:shallowReadonly(响应性数据)
  • shallowReadonly 修饰的数据,浅层数据不可被修改,但深层数据可以被修改
<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 修饰的响应式数据变为普通数据:toRaw(响应式数据)
  • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,都不会引起页面更新
<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>

可以发现,toRaw 修饰的数据,会变为普通数据,修改普通数据,页面不会重新渲染
但是数据是已经被改变了的,页面如果重新渲染的话,还是会显示最新数据

markRaw

  • 用于标记一个对象数据,使其永远不能成为一个响应式数据
<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>

可以发现,正常接收的对象数据,是可以被修改并渲染到页面上的;
但是,用 markRaw 修饰的对象数据,数据会被修改,但不会被渲染到页面上(当然,页面重新渲染时,还是会显示最新数据)

provide & inject

  • provide 用于传递数据给后代组件:provide("XXX", 数据值)
  • inject 用于接收祖先组件传递的数据: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>

此时,不论在哪个组件修改数据,数据都会被修改成功,并渲染到页面上

  • 如果想后代组件无法修改并渲染数据,可以使用 toRaw 修饰数据:

    此时,后代组件无法修改并渲染接收的数据,但是数据是已经被修改了的,页面重新渲染的话,还是会显示最新数据

<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>
  • 如果不允许修改数据,可以使用 readonly 修饰数据:

    此时,只有父级组件可以修改数据,后代组件不能修改接收的数据

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

判断响应式数据

  1. isRef - 检查一个值是否由 ref 修饰
  2. isReactive - 检查一个对象是否由 reactive 修饰
  3. isReadonly - 检查一个对象是否由 readonly 修饰
  4. isProxy - 检查一个对象是否由 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>

猜你喜欢

转载自blog.csdn.net/Superman_H/article/details/126276553