当前位置:  首页>> 技术小册>> Vue.js从入门到精通(三)

12.3.3 ref() 方法:Vue 3 Composition API 的核心构件

在 Vue 3 中,Composition API 的引入为开发者提供了一种全新的方式来组织和重用逻辑。作为 Composition API 的核心工具之一,ref() 方法扮演着至关重要的角色。它不仅简化了响应式数据的创建过程,还促进了组件逻辑的清晰分离和复用。本章将深入解析 ref() 方法的原理、用法、最佳实践以及在复杂场景中的应用。

12.3.3.1 理解 ref() 方法的基础

ref() 是 Vue 3 中用于创建一个响应式引用的函数。与 Vue 2 的响应式系统不同,Vue 3 引入了 Proxy 来实现更深层次的响应式,而 ref() 正是这一新系统下的产物。当你调用 ref() 并传入一个初始值时,它会返回一个响应式且可变的 ref 对象。这个对象拥有一个 .value 属性,用于访问或修改其内部的值。

基本用法示例

  1. import { ref } from 'vue';
  2. const count = ref(0);
  3. console.log(count.value); // 输出: 0
  4. count.value++;
  5. console.log(count.value); // 输出: 1

在这个例子中,count 是一个响应式的引用,其内部值通过 .value 属性进行访问和修改。每当 .value 的值发生变化时,任何依赖于这个 ref 的视图或计算属性都会自动更新。

12.3.3.2 ref() 与原始值的差异

使用 ref() 创建的响应式引用与直接使用原始值(如数字、字符串等)在行为上存在显著差异。原始值在 JavaScript 中是按值传递的,而 ref() 返回的引用是按引用传递的。这意味着当你将 ref() 的返回值传递给函数或组件时,你实际上传递的是对内部值的引用,而不是值本身。

对比示例

  1. // 使用原始值
  2. let primitiveCount = 0;
  3. function incrementPrimitive() {
  4. primitiveCount++;
  5. }
  6. // 使用 ref()
  7. const refCount = ref(0);
  8. function incrementRef() {
  9. refCount.value++;
  10. }
  11. incrementPrimitive(); // 原始值变化
  12. console.log(primitiveCount); // 输出: 1
  13. incrementRef(); // ref 值变化
  14. console.log(refCount.value); // 输出: 1

在组件间传递数据时,ref() 的这种特性尤为重要,因为它允许父组件通过 props 将响应式引用传递给子组件,子组件则可以通过修改 .value 来更新数据,从而触发视图的更新。

12.3.3.3 在模板中使用 ref()

虽然 ref() 主要是为了在 JavaScript 逻辑中使用,但 Vue 3 提供了 .value 的自动解包功能,使得在模板中可以直接访问 ref 的值而无需 .value

模板示例

  1. <template>
  2. <div>
  3. <p>{{ count }}</p>
  4. <button @click="increment">Increment</button>
  5. </div>
  6. </template>
  7. <script>
  8. import { ref } from 'vue';
  9. export default {
  10. setup() {
  11. const count = ref(0);
  12. function increment() {
  13. count.value++;
  14. }
  15. return {
  16. count,
  17. increment
  18. };
  19. }
  20. }
  21. </script>

在这个例子中,尽管 count 是一个 ref 对象,但在模板中可以直接使用 {{ count }} 来访问其 .value 属性,无需显式编写 .value

12.3.3.4 ref() 在 Composition API 中的高级用法

ref() 的强大之处不仅限于基本的数据绑定,它还可以与其他 Composition API 函数(如 reactivecomputedwatch 等)结合使用,以实现更复杂的功能。

watch 结合使用

  1. import { ref, watch } from 'vue';
  2. const counter = ref(0);
  3. watch(counter, (newValue, oldValue) => {
  4. console.log(`Counter changed from ${oldValue} to ${newValue}`);
  5. });
  6. // 稍后,当 counter.value 改变时,watch 回调将被触发

computed 结合使用

  1. import { ref, computed } from 'vue';
  2. const base = ref(10);
  3. const double = computed(() => base.value * 2);
  4. // 当 base.value 改变时,double 会自动更新

12.3.3.5 最佳实践

  • 避免在模板中直接修改 ref 的值:虽然技术上可行,但直接在模板中修改 ref 的值(如通过事件处理函数)可能会导致代码难以理解和维护。建议将所有逻辑封装在 setup() 函数内。
  • 合理使用 .value:在 JavaScript 逻辑中始终通过 .value 访问或修改 ref 的值。在模板中,Vue 会自动处理解包。
  • 结合其他 Composition API 使用ref() 与其他 Composition API 函数(如 reactivecomputedwatch 等)的配合使用,可以构建出既灵活又强大的响应式系统。
  • 考虑使用 shallowRef:对于大型对象或数组,如果你只需要响应式地追踪其引用变化而非内部属性的变化,可以使用 shallowRef 来优化性能。

12.3.3.6 总结

ref() 方法作为 Vue 3 Composition API 的基石之一,极大地丰富了 Vue 应用的开发方式和可能性。通过掌握 ref() 的基本用法、理解其与原始值的差异、学习在模板中的使用方式、探索与其他 Composition API 的结合使用以及遵循最佳实践,你将能够更加高效、灵活地构建 Vue 应用。随着 Vue 3 生态的不断发展,ref() 及其背后的响应式原理将继续为开发者们带来惊喜和便利。


该分类下的相关小册推荐: