响应式变化存在的问题:值传递是无法实现【响应式变化】为此对应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如何响应式变化:{{ testValueWatch }}</view>
        <view>测试props的对象传参给dada如何响应式变化:{{ testObj.number }}</view>
    </view>
</template>

<script>

export default {
    name: "test",
    data() {
        return {
            // 基于props.testValueWatch实现响应式的参数
            testValueWatch: 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.testValueWatch = 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>

Logo

前往低代码交流专区

更多推荐