Vue 3 组合式 API 指南:响应式状态管理与跨组件通信

引言

随着 Vue 3 的发布,Vue 引入了一个新的编程范式------组合式 API(Composition API)。这一新特性旨在解决 Options API 在处理复杂逻辑时的一些局限性,并提供了一种更灵活、更可重用的方式来组织和重用代码

组合式 API 基础

setup 函数的概念和作用

在 Vue 组合式 API 中,setup 函数是组件的入口点,它在组件实例被创建时调用,但在任何生命周期钩子之前执行。setup 函数的主要作用是初始化响应式状态、计算属性、方法和侦听器,并将它们暴露给模板和组件的其他部分。

javascript 复制代码
import { ref, reactive, computed, watch } from 'vue';

export default {
  setup() {
    // 初始化响应式状态和功能
    return {
      // 暴露给模板和组件其他部分的响应式状态和功能
    };
  }
};

响应式引用 ref 和响应式对象 reactive 的使用方法

在 Vue 3 中,refreactive 是创建响应式状态的两个主要工具。

  • ref 用于创建单个响应式值,它返回一个响应式的引用对象。当引用的值是基本数据类型时,Vue 会自动将其包装在对象中。
javascript 复制代码
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    // 通过 .value 访问和修改响应式值
    console.log(count.value); // 输出 0
    count.value++;
    console.log(count.value); // 输出 1

    return {
      count
    };
  }
};
  • reactive 用于创建一个响应式对象。它返回一个响应式的代理对象,该对象的属性访问和修改都是响应式的。(实际上,ref底层就是reactive实现的,实际开发中一般ref用的多)
javascript 复制代码
import { reactive } from 'vue';

export default {
  setup() {
    const state = reactive({ count: 0 });

    // 直接访问和修改响应式对象的属性
    console.log(state.count); // 输出 0
    state.count++;
    console.log(state.count); // 输出 1

    return {
      state
    };
  }
};

使用 computed 和 watch 创建计算属性和侦听器

computedwatch 是 Vue 组合式 API 中用于处理计算属性和侦听器的工具。

  • computed 用于创建计算属性,它接受一个 getter 函数,并返回一个只读的响应式引用。
javascript 复制代码
import { ref, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const doubleCount = computed(() => count.value * 2);

    // 访问计算属性
    console.log(doubleCount.value); // 输出 0

    return {
      count,
      doubleCount
    };
  }
};
  • watch 用于创建侦听器,它监视一个或多个响应式引用的变化,并在变化时执行一个回调函数。
javascript 复制代码
import { ref, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);

    watch(count, (newValue, oldValue) => {
      console.log(`Count changed from ${oldValue} to ${newValue}`);
    });

    return {
      count
    };
  }
};

provide 和 inject

在 Vue.js 中,provideinject 是两个用于实现跨组件依赖注入的 API。它们允许一个祖先组件定义可供其所有子孙组件使用的数据或方法,而无需通过逐层传递 props 或使用事件发射器。

provide

provide 函数允许你在组件内部提供一个值,这个值可以被其所有子孙组件注入。provide 可以在组件的 setup 函数中使用,也可以在组件的 methodscomputedwatch 中使用。

javascript 复制代码
import { provide } from 'vue';

export default {
  setup() {
    // 提供一个响应式对象
    const state = reactive({ count: 0 });

    // 提供一个方法
    const increment = () => {
      state.count++;
    };

    // 使用 provide 函数提供数据
    provide('state', state);
    provide('increment', increment);

    // ...
  }
};

在上面的例子中,stateincrement 方法被提供给所有子孙组件。

inject

inject 函数用于在子孙组件中注入由祖先组件提供的数据或方法。inject 可以在组件的 setup 函数中使用,也可以在组件的 methodscomputedwatch 中使用。

javascript 复制代码
import { inject } from 'vue';

export default {
  setup() {
    // 注入 'state' 和 'increment'
    const state = inject('state');
    const increment = inject('increment');

    // 使用注入的数据和方法
    console.log(state.count); // 输出 0
    increment(); // 增加计数

    // ...
  }
};

在上面的例子中,stateincrement 被注入到子孙组件中,并可以像本地数据一样使用。

注意事项

  • provideinject 是成对使用的,只有当祖先组件提供了某个值,子孙组件才能注入这个值。
  • provideinject 提供的值是响应式的,这意味着如果提供的值发生变化,所有注入了这个值的子孙组件都会自动更新。
  • provideinject 可以在组件的任何生命周期钩子中使用,但通常在 setup 函数中使用,以确保在组件初始化时提供和注入值。

通过使用 provideinject,开发者可以更灵活地管理组件之间的依赖关系,特别是在大型应用中,这有助于减少组件之间的耦合度,提高代码的可维护性。

子孙组件能改动inject注入的值吗

孙组件不能直接修改通过 inject 注入的响应式数据。这是为了保持数据流的清晰和组件之间的独立性,避免潜在的副作用和难以追踪的错误。

然而,如果你确实需要在子孙组件中修改注入的值,你可以通过以下方法实现:

1.使用 refreactive 提供响应式数据

如果你使用 refreactive 提供响应式数据,那么子孙组件可以通过 .value 属性来修改这个值。

javascript 复制代码
// 祖先组件
import { provide, reactive } from 'vue';

export default {
  setup() {
    const state = reactive({ count: 0 });

    provide('state', state);

    // ...
  }
};

// 子孙组件
import { inject } from 'vue';

export default {
  setup() {
    const state = inject('state');

    // 修改注入的响应式数据
    state.count++;

    // ...
  }
};

2.提供一个方法来修改数据

你可以在祖先组件中提供一个方法,该方法可以修改响应式数据。然后,这个方法可以被子孙组件注入并调用。

javascript 复制代码
// 祖先组件
import { provide } from 'vue';

export default {
  setup() {
    const state = reactive({ count: 0 });
    const increment = () => {
      state.count++;
    };

    provide('state', state);
    provide('increment', increment);

    // ...
  }
};

// 子孙组件
import { inject } from 'vue';

export default {
  setup() {
    const increment = inject('increment');

    // 调用注入的方法来修改数据
    increment();

    // ...
  }
};

3.使用 readonly 创建只读引用

如果你不希望子孙组件修改注入的值,可以使用 readonly 创建一个只读引用。

typescript 复制代码
// 祖先组件
import { provide, reactive, readonly } from 'vue';

export default {
  setup() {
    const state = reactive({ count: 0 });

    provide('state', readonly(state));

    // ...
  }
};

// 子孙组件
import { inject } from 'vue';

export default {
  setup() {
    const state = inject('state');

    // 尝试修改注入的值将会失败
    // state.count = 1; // 这将不会工作

    // ...
  }
};

总结

Vue 3 的组合式 API 通过 setup 函数提供响应式状态管理,支持使用 refreactive 创建响应式数据,computedwatch 处理计算属性和侦听器。同时,provideinject 允许跨组件进行依赖注入,实现数据和方法的共享。这些特性提升了代码的组织性、可重用性以及组件间的解耦。

希望这篇文章能帮助到你

相关推荐
呼啦啦小魔仙几秒前
elpis项目DSL设计分享
前端
李李记1 分钟前
别让 “断字” 毁了 Canvas 界面!splitByGrapheme 轻松搞定非拉丁文本换行
前端·canvas
来金德瑞2 分钟前
快速掌握 ProseMirror 的核心概念
前端
ygria6 分钟前
样式工程化:如何实现Design System
前端·前端框架·前端工程化
墨渊君1 小时前
“蒙”出花样!用 CSS Mask 实现丝滑视觉魔法
前端·css
huabuyu2 小时前
基于 React + MarkdownIt 的 Markdown 渲染器实践:支持地图标签和长按复制
前端
芦苇Z2 小时前
HTML <a> 标签的 rel 属性全解析:安全、隐私与 SEO 最佳实践
前端·html
在这儿不行2 小时前
Android 15边到边模式
前端
源猿人2 小时前
企业级文件浏览系统的Vue实现:架构设计与最佳实践
前端·javascript·数据可视化
红红大虾2 小时前
Defold引擎中关于CollectionProxy的使用
前端·游戏开发