# 1. 解构的数据不是响应式的 (toRef/toRefs)

App 为根组件 下面 Home 例子都被此组件引用

vue
// App.vue 
<template>
  <div>
    <home></home>
  </div>
</template>
<script>
import Home from "./Home.vue";
export default {
  components: {
    Home,
  },
};
</script>
<style scoped>
</style>
vue
// Home.vue
<template>
  <div> 
    <!-- -->
    <h2>{{ name }}-{{ age }}</h2> 
    <button @click="changeAge">修改age</button>
  </div>
</template>
<script>
import { reactive } from "vue";
export default {
  setup() {
    const info = reactive({ name: "Neko", age: 16 });
    // 注意这里可以解构,但是解构的数据不是响应式的!
    let { name, age } = info;
    const changeAge = () => {
      // 这里是解构后的 age, 渲染的页面没有发送变化,但是数据已经发送了改变
      age++;
      console.log("解构的age:", age);
      console.log("原对象:", info);
    };
    return {
      name,
      age,
      changeAge,
    };
  },
};
</script>
<style scoped>
</style>

参考结果:

step_toRef-toRefs

# 2. 使用 toRef 对某一个属性进行响应式

vue
// Home.vue
<template>
  <div>
    <!--  -->
    <h2>{{ name }}-{{ age }}</h2>
    <button @click="changeAge">修改age</button>
  </div>
</template>
<script>
import { reactive, toRef } from "vue";
export default {
  setup() {
    const info = reactive({ name: "Neko", age: 16 });
    // 使用 toRefs 包裹住 info 再解构,使得数据变成响应式!
    let { name } = info;
    // 这里不需要要解构,之间用变量接收就 OK~
    let age = toRef(info, "age"); // 第一个参数是对象名,第二个则是对象里的属性
    const changeAge = () => {
      // 这里和 ref 一样,应使用 value 来获取,并对 age.value++
      age.value++;
      console.log("解构的age:", age);
      console.log("原对象:", info);
    };
    return {
      name,
      age,
      changeAge,
    };
  },
};
</script>
<style scoped>
</style>

参考结果:这里它们的引用地址也是一样的!

step_toRef-toRefs

# 3. 使用 toRefs 使数据变成响应式

vue
<template>
  <div> 
    <!--  -->
    <h2>{{ name }}-{{ age }}</h2>
    <button @click="changeAge">修改age</button>
  </div>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
  setup() {
    const info = reactive({ name: "Neko", age: 16 });
    // 使用 toRefs 包裹住 info 再解构,使得数据变成响应式!
    let { name, age } = toRefs(info);
    const changeAge = () => {
      // 这里和 ref 一样,应使用 value 来获取,并对 age.value++
      age.value++;
      console.log("解构的age:", age);
      console.log("原对象:", info);
    };
    return {
      name,
      age,
      changeAge,
    };
  },
};
</script>
<style scoped>
</style>

参考结果:注意原对象里的 age 也发生了改变是因为它们的引用地址也是一样的!

step_toRef-toRefs

# 4. 总结

  • 提问:首先它们应该是什么时候用?

  • 要对数据解构时可以用

  • toRef 和 toRefs 包裹的必须都是响应式的对象 (reactive/ref)

  • toRef 可以对某一个对象的某个属性进行响应式

  • toRefs 则是对整个对象进行响应式