【Vue3响应式】ref、reactive,以及toRefs 函数

Vue3的ref和reactive区别

  • 一、 ref
    • ref的作用
    • ref的代码示例
  • 二、reactive
    • reactive的作用
    • reactive的代码示例
      • reactive的基础例子
      • reactive包含嵌套对象和数组的例子
  • 三、ref和reactive的区别
  • 四、toRefs 函数
    • 什么是 toRefs 函数?
    • 如何使用 toRefs 函数?
    • 注意事项
  • 五、面试可能会问的问题

Vue3中的ref和reactive都是响应式数据的实现方式。在Vue3中,我们可以使用ref来将基本数据类型包装为一个响应式对象,使用reactive将对象包装为响应式对象。本文将介绍这两种响应式数据的实现方式以及它们之间的区别。

一、 ref

ref的作用

ref是Vue3提供的一种用于包装基本数据类型的响应式对象的实现方式。在Vue3中,使用ref可以将基本数据类型(如字符串、数字、布尔值等)包装为响应式对象。当这些基本数据类型的值发生变化时,Vue3会自动更新视图中相应的内容。

ref的代码示例

下面是一个使用ref的示例:

<template>
  <div>
    <p>{{ message }}p>
    <button @click="updateMessage">更新button>
  div>
template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const message = ref('Hello, World!');
    
    const updateMessage = () => {
      message.value = 'Hello, Vue3!';
    };
    
    return {
      message,
      updateMessage
    };
  }
};
script>

在这个例子中,我们使用了ref来包装一个字符串类型的数据。在setup函数中,我们将ref返回的响应式对象作为组件实例的一个属性,同时也将updateMessage函数返回给模板。当updateMessage函数被调用时,message的值会被更新为’Hello, Vue3!',并且视图中显示的内容也会被更新。

需要注意的是,在使用ref包装基本数据类型时,我们需要通过.value来访问这个值。这是因为ref返回的是一个包含.value属性的响应式对象,而不是一个基本数据类型的值。

二、reactive

reactive的作用

reactive是Vue3提供的一种用于包装对象的响应式对象的实现方式。在Vue3中,使用reactive可以将对象包装为一个响应式对象。当这个对象的属性发生变化时,Vue3会自动更新视图中相应的内容。

reactive的代码示例

reactive的基础例子

下面是一个使用reactive的例子:

<template>
  <div>
    <p>{{ user.name }}p>
    <button @click="updateUserName">更新button>
  div>
template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const user = reactive({
      name: 'John Doe',
      age: 30
    });
    
    const updateUserName = () => {
      user.name = 'Jane Doe';
    };
    
    return {
      user,
      updateUserName
    };
  }
};
script>

在这个例子中,我们使用了reactive来包装一个包含name和age两个属性的对象。在setup函数中,我们将reactive返回的响应式对象作为组件实例的一个属性,同时也将updateUserName函数返回给模板。当updateUserName函数被调用时,user对象的name属性会被更新为’Jane Doe’,并且视图中显示的内容也会被更新。
需要注意的是,在使用reactive包装对象时,所有的属性都会被包装为响应式对象,包括嵌套的对象和数组。这意味着当嵌套对象或数组的属性发生变化时,也会触发相应的视图更新。
下面是一个包含嵌套对象和数组的例子:

reactive包含嵌套对象和数组的例子

<template>
  <div>
    <p>{{ user.name }}p>
    <p>{{ user.address.city }}p>
    <ul>
      <li v-for="hobby in user.hobbies" :key="hobby">{{ hobby }}li>
    ul>
    <button @click="updateUser">更新button>
  div>
template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const user = reactive({
      name: 'John Doe',
      age: 30,
      address: {
        city: 'New York',
        country: 'USA'
      },
      hobbies: ['reading', 'swimming', 'hiking']
    });
    
    const updateUser = () => {
      user.name = 'Jane Doe';
      user.address.city = 'San Francisco';
      user.hobbies.push('yoga');
    };
    
    return {
      user,
      updateUser
    };
  }
};
script>

在这个例子中,我们使用reactive来包装一个包含嵌套对象和数组的对象。在setup函数中,我们将reactive返回的响应式对象作为组件实例的一个属性,同时也将updateUser函数返回给模板。当updateUser函数被调用时,user对象的name属性、address对象的city属性和hobbies数组的内容都会被更新,并且视图中显示的内容也会被更新。

三、ref和reactive的区别

在使用ref和reactive时,需要注意它们之间的区别。ref适用于包装基本数据类型,而reactive适用于包装对象。此外,ref返回的是一个包含.value属性的响应式对象,而reactive返回的是一个包装后的响应式对象。

下面是一个使用ref和reactive的区别的例子:

<template>
  <div>
    <p>{{ message }}p>
    <p>{{ user.name }}p>
    <button @click="updateData">更新button>
  div>
template>

<script>
import { ref, reactive } from 'vue';

export default {
  setup() {
    const message = ref('Hello, World!');
    const user = reactive({
      name: 'John Doe',
      age: 30
    });
    
    const updateData = () => {
      message.value = 'Hello, Vue3!';
      user.name = 'Jane Doe';
    };
    
    return {
      message,
      user,
      updateData
    };
  }
};
script>

在这个例子中,我们同时使用了ref和reactive。当updateData函数被调用时,我们使用ref更新了message的值,同时也使用reactive更新了user对象的name属性的值。需要注意的是,在更新message的值时,我们需要使用.value来访问它的值,而在更新user对象的name属性的值时,我们直接使用了对象的属性访问方式。

四、toRefs 函数

Vue 3 中的 toRefs 函数是一个非常有用的工具,它可以将一个响应式对象转换为一组响应式属性。这个函数可以用于将父组件中的响应式对象传递给子组件,并在子组件中以单独的响应式属性的形式使用它们。

什么是 toRefs 函数?

在 Vue 3 中,我们可以使用 ref 和 reactive 来创建响应式数据。ref 可以用于创建单个值的响应式数据,而 reactive 则可以用于创建包含多个属性的响应式对象。

但是,在某些情况下,我们希望将一个响应式对象的属性单独作为响应式属性使用,而不是将整个对象作为一个响应式数据使用。这时就可以使用 toRefs 函数。

toRefs 函数的作用是将一个响应式对象转换为一个对象,该对象的属性均为单独的响应式属性,这些属性与原始响应式对象的属性具有相同的响应式性质。

如何使用 toRefs 函数?

下面是一个示例,演示了如何使用 toRefs 函数将一个响应式对象转换为一组响应式属性:

<template>
  <div>
    <p>Count: {{ count }}p>
    <button @click="increment">Incrementbutton>
    <ChildComponent :propsData="toRefs(childData)" />
  div>
template>

<script>
import { reactive, toRefs } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
  setup() {
    const data = reactive({
      count: 0,
      message: 'Hello!',
    });

    const childData = reactive({
      name: 'Child',
      age: 10,
    });

    const increment = () => {
      data.count++;
    };

    return {
      ...toRefs(data),
      childData,
      increment,
    };
  },
};
script>

在这个例子中,父组件的 data 对象包含一个 count 属性,表示一个计数器。父组件通过 toRefs 函数将这个对象转换为一组响应式属性,并将这些属性传递给了子组件。子组件可以像使用普通的响应式属性一样使用这些属性。

注意事项

需要注意的是,toRefs 函数返回的对象中的属性并不是响应式的,而是与原始响应式对象的属性具有相同的响应式性质。这意味着,如果原始响应式对象的属性被更新了,返回的对象中的属性也会被更新。但是,如果返回的对象中的属性被直接更新了,原始响应式对象中的对应属性不会被更新。

五、面试可能会问的问题

Vue3的响应式原理——一定要背下来!

Vue3的响应式原理是通过Proxy(代理)对对象的属性值进行读写、添加、删除、进行劫持,通过Reflect(反射)动态对被代理对象的属性值进行特定的操作,由于Proxy和Reflect不支持IE浏览器,这也是Vue3不支持IE浏览器的主要原因之一!

你可能感兴趣的:(javascript,vue.js,前端)