返回 导航

Vue.js

hangge.com

Vue.js 3 - Composition API使用详解2(reactive、ref基本用法)

作者:hangge | 2026-04-25 09:46
    若要使用 Options API 编写代码,可以在 data 选项中定义响应式数据。如果在 setup 函数中也需要定义响应式数据,那么可以使用 Vue.js3 提供的响应式 APIreactiveref。 下面通过样例演示 reactiveref 的使用。

二、reactive、ref 基本用法

1,reactive 函数使用

(1)如果想在 setup 函数中返回响应式数据,可以使用 reactive 函数。该函数可以将数据转换为响应式的,并且响应式是深层的--它影响所有嵌套属性。
提示:其底层原理基于 ES2015Proxy 实现,所以 reactive 函数的返回值是一个对象的响应式代理。

(2)我们首先创建一个 ReactiveAPI.vue 组件,代码如下:
  • 首先从 vue 中导入 reactive 函数,并在 setup 中调用该函数。reactive 函数需要接收一个对象或数组类型的参数,并返回一个响应式对象。这里,我们向 reactive 函数传递一个对象,在该对象中定义 counter 属性。 
  • 接着,将 reactive 返回的响应式对象 state 作为 setup 函数的返回值,并在模板中显示 state 对象中的 counter 属性。 
  • 然后,当用户单击“+1”按钮时,会触发 increment 函数的回调,该函数实现了对 state 响应式对象中的 counter 属性的加 1 操作。 
<template>
  <div class="reactive-api" style="border:1px solid #ddd;margin:10px">
    ReactiveAPI组件
    <h4>当前计数: {{state.counter}}</h4>
    <button @click="increment">+1</button>
  </div>
</template>
<script>
  import { reactive } from 'vue'; // 1.导入响应式api
  export default {
    setup() {
      // 2.定义响应式数据 
      const state = reactive({
        counter: 100
      })
      // console.log(state)
      const increment = () => {
        state.counter++; // 3.局部函数使用响应式数据
        console.log(state.counter);
      }
      return {
        state, // 4.返回响应数据
        increment // 5.返回定义的方法(等同于在methods中定义方法)
      }
    }
  }
</script>

(3)接着在 App.vue 中使用 ReactiveAPI.vue 组件:
<template>
  <div class="app" style="border:1px solid #ddd;margin:4px">
    App组件
    <ReactiveAPI></ReactiveAPI>
  </div>
</template>

<script>
import ReactiveAPI from './ReactiveAPI.vue';
export default {
  components: {
    ReactiveAPI
  }
}
</script>

(4)运行效果如下,可以看到,counter 的值被显示出来,当单击“+1”按钮时,会回调 increment 函数来修改 counter 变量,这时,页面的数值会响应式刷新。这是因为使用 reactive 函数处理的数据,当数据被使用时,就会进行依赖收集;当数据发生改变时,所有收集到的依赖都会进行对应的响应式操作,如更新页面。 
提示:事实上 data 选项返回的对象在 Vue.js3 内部也交给了 reactive 函数,将其变成响应式对象。

2,ref 函数使用

(1)reactive 函数对传入数据的类型是有限制的,必须是一个对象或数组类型。如果传入一个基本数据类型(StringNumberBoolean),则会出现警告。
  • 例如,向 reactive 函数传递一个 Hello World 字符串,控制台会出现“value cannot be made reactive:Hello World”的警告。

(2)为了解决上述问题,Vue.js 3 提供了另一个响应式 APIref,该 API 有如下特点:
  • ref 函数接收一个值,返回一个响应式、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value。 
  • ref 对象内部值是通过该对象的 .value 属性维护的,比如可以通过.value 为该 ref 对象赋新值。 
  • 如果将对象分配为 ref 函数的值,则它将被 reactive 函数处理为深层的响应式对象。

(3)这里我们新建一个 RefAPI.vue 组件,代码如下所示:
  • 首先从 vue 中导入 ref 函数,并在 setup 函数中调用该函数。在此处,我们向 ref 函数传递了一个基本数据类型:数字 100。 
  • 接着,将 ref 函数返回的 counter 响应式对象作为 setup 函数的返回值返回,并在模板中显示该响应式对象的内部值(value)。当用户单击“+1”按钮时,会调用 setup 函数返回的 increment 函数,该函数实现了对 counter 响应式对象内部值进行加 1 操作,并通过 .value 访问该对象的内部值。 
注意:在模板中使用 ref 对象时,Vue.js3 会自动进行解包操作,不需要通过 .value 的方式访问内部值。但是,在 setup 函数内部不会自动解包,因此仍需要使用 .value 的方式访问内部值。
<template>
  <div class="ref-api" style="border:1px solid #ddd;margin:10px">
    RefAPI组件
    <!-- 当我们在template模板中使用ref对象, 它会自动进行解包,不需要通过value属性访问 -->
    <h4>当前计数: {{counter}}</h4>
    <button @click="increment">+1</button>
  </div>
</template>
<script>
  import { ref } from 'vue'; // 1.导入响应式api
  export default {
    setup() {
      // 2.定义响应式数据(ref函数接收基本数据类型的参数)
      // counter是一个ref的可响应式的引用对象,可通过value属性获取和修改值 
      const counter = ref(100)
      // console.log(counter)
      const increment = () => {
        counter.value++; // 3.局部函数修改响应式数据(不会自动解包)
        console.log(counter.value); // 获取响应式数据
      }
      return {
        counter, // 4.返回响应数据
        increment // 5.返回定义的方法(等同于在methods中定义方法)
      }
    }
  }
</script>

(4)修改 App.vue 组件,代码如下所示:
<template>
  <div class="app" style="border:1px solid #ddd;margin:4px">
    App组件
    <RefAPI></RefAPI>
  </div>
</template>

<script>
import RefAPI from './RefAPI.vue';
export default {
  components: {
    RefAPI
  }
}
</script>

(5)运行效果如下图所示,可以看到,counter 的值被显示出来,当单击“+1”按钮时,会回调 increment 函数来修改 counter 变量,这时页面的数值会响应式刷新。

附:嵌套在其他对象中的 ref 对象使用效果

(1)ref 对象如果嵌套在普通对象或者 reactive 响应式对象中时,要注意:
  • 如果普通对象包含 ref 对象,那么在模板中引用普通对象中的 ref 对象时,会自动解包。 
  • 如果 reactive 响应式对象包含 ref 对象,那么在模板中引用 reactive 响应式对象中的 ref 对象时,也会自动解包。 
(2)我们将前面的 RefAPI.vue 组件代码修改成如下:
<template>
  <div class="ref-api-other" style="border:1px solid #ddd;margin:10px">
    RefAPIOther组件(演示ref的浅层解包)
    <h4>当前计数: {{ counter }}</h4>
    <!-- 如果普通对象包裹的是ref对象时,那么info中的ref对象可以解包 -->
    <h2>当前计数: {{ info.counter }}</h2>
    <!-- 如果最外层包裹的是一个reactive可响应式对象, 那么info中的ref对象可以解包 -->
    <h2>当前计数: {{ reactiveInfo.counter }}</h2>
    <button @click="increment">+1</button>
  </div>
</template>
<script>
import { reactive, ref } from 'vue'; // 1.导入响应式api
export default {
  setup() {
    // 2.定义响应式数据
    let counter = ref(100);

    // 普通对象包含ref响应式对象
    const info = {
      counter
    }
    // reactive响应式对象包含ref响应式对象
    const reactiveInfo = reactive({
      counter
    })
    const increment = () => {
      counter.value++;
      console.log(counter.value);
    }
    return {
      counter,
      info,
      reactiveInfo,
      increment
    }
  }
}
</script>

(3)浏览器运行效果如下:
评论

全部评论(0)

回到顶部