欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Vue2+Vue3】props参数赋值给data属性【如何实现响应式变化-如何解决值传递无法响应式的问题】

程序员文章站 2024-01-02 21:24:22
...

响应式变化存在的问题:值传递是无法实现【响应式变化】为此对应props的值传参给data,必须重新包裹封装成一个对象【实现引用传参】才能解决响应式的问题

Vue2的解决办法【要自己封装对象,且结合watch】比较复杂

<template>
    <view class="content">
        <Test :value="value" :value-obj="valueObj"/>
        <button @click="changeValue">改变value</button>
        <button @click="changeValueObj">改变valueObj</button>
    </view>
</template>

<script>

import Test from "../test.vue";

export default {
    components: {
        Test,
    },
    data() {
        return {
            value: "",
            valueObj: {
                number: 1,
            },
        };
    },
    methods: {
        changeValue() {
            this.value += "!";
        },
        changeValueObj() {
            this.valueObj.number += 1;
        },
    },
};
</script>
<template>
    <view>
        <view>测试props的值传参给dada如何响应式变化:{{ testValueWatchObj.value }}</view>
        <view>测试props的对象传参给dada如何响应式变化:{{ testObj.number }}</view>
    </view>
</template>

<script>

export default {
    name: "test",
    data() {
        return {
            testValueWatchObj: {
                /**
                 * 封装【props属性】的响应式对象【props此属性变化->此对象跟着变化】
                 *      1、把props中的value值参数赋值给data属性后封装成一个对象【变成引用传参即可响应性变化】
                 *      2、这里的响应式变化是【通过watch监听】props.value的改变,会影响当前对象的value的改变!
                 *      3、但是当前对象的value的改变,不会改变props.value的值!
                 */
                "value": this.value,
            },
            testObj: this.valueObj,
        };
    },
    updated() {
        console.log("testObj====", this.testObj);

        this.testObj.aa = "我是新添加的值";


        console.log("===valueObj===", this.valueObj);
    },

    watch: {
        value(newValue) {
            /**
             * 监听value的值的变化,响应式改变this.watchPropsValueObj对象
             */
            this.testValueWatchObj.value = newValue;
        },
    },
    props: {
        value: {
            /*
                直接值传参【props赋值给data数据的值传递,不会响应式变化】
             */
            type: String,
            default: "",
        },
        valueObj: {
            /*
                直接对象传参【props赋值给data数据的引用传参,双向响应式变化】
             */
            type: Object,
        },
    },
};
</script>

Vue3 的解决办法【使用toRef函数,非常简单】

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld :value="value" :value-obj="valueObj"/>

  <button @click="changeValue">改变value</button>
  <button @click="changeValueObj">改变valueObj</button>

</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";
import { reactive, toRefs } from "vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
  setup() {
    let _data = reactive({
      value: "#",
      valueObj: {
        number: 1,
      },
    });

    function changeValue() {
      this.value += "!";
    }

    function changeValueObj() {
      this.valueObj.number += 1;
    }


    return {
      ...toRefs(_data),
      changeValue,
      changeValueObj,
    };
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
<template>
  <div class="hello">
    <div>测试props的值传参给dada如何响应式变化:{{ testValue }}</div>
    <div>测试props的对象传参给dada如何响应式变化:{{ testValueObj.number }}</div>
  </div>
</template>

<script>

import { reactive, toRefs, toRef } from "vue";

export default {
  name: "HelloWorld",
  props: {
    value: {
      type: String,
      default: "",
    },
    valueObj: {
      type: Object,
    },
  },
  setup(props, context) {
    console.log(props.value);
    let _data = reactive({
          // 由于props的value属性是一个值类型,为此这里必须转换成toRef类型变成引用类型即可响应式变化!
          testValue: toRef(props, "value"),
          testValueObj: props.valueObj,
        },
    );

    return {
      ...toRefs(_data),
    };
  },
}
;
</script>

上一篇:

下一篇: