[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式

简介: [译] 用 Vue 3 Composition API 实现 React Context/Provider 模式

原文:markus.oberlehner.net/blog/contex…

React Context API 提供了一种 不用在组件树中逐层传递 props (也称 prop drilling)的前提下 共享被多个组件都需要的属性 (比如用户设置、UI 主题等)的方式。尽管 Vue.js 没有自带的完全一致的抽象,但在本文中,我们将看到 在 Vue 3 中,我们已经拥有了可以快速复刻前者功能的所有必需工具。

用户设置 provider

在本例中,来看看如何运用这一模式 让某些信息全局可用

如下的 ProvideUserSettings 组件,提供了一个反应式的 state 及一些默认值,还有一个 update() 函数用以设置 state 对象。


// src/components/ProvideUserSettings.js
import {
  provide,
  reactive,
  readonly,
  toRefs,
} from 'vue';
// 使用 symbols 制造独特标识
export const UserSettingsStateSymbol = Symbol('User settings state provider identifier');
export const UserSettingsUpdateSymbol = Symbol('User settings update provider identifier');
export default {
  setup() {
    const state = reactive({
      language: 'en',
      theme: 'light',
    });
    
    // 使用 `toRefs()` 确保其在消费者组件中广泛可用
    // 而 `readonly()` 预防了用户修改全局状态
    provide(UserSettingsStateSymbol, toRefs(readonly(state)));
    const update = (property, value) => {
      state[property] = value;
    };
    provide(UserSettingsUpdateSymbol, update);
  },
  render() {
    // 该 provider 组件是 “renderless” 的
    // 其自身不渲染任何东西
    return this.$slots.default();
  },
};

下面来看看如何在应用中使用 ProvideUserSettings 组件:


<!-- src/App.vue -->
<script>
import ProvideUserSettings from './components/ProvideUserSettings';
export default {
  name: 'App',
  components: {
    ProvideUserSettings,
  },
};
</script>
<template>
  <ProvideUserSettings>
    <div>
      <!-- ... -->
    </div>
  </ProvideUserSettings>
</template>

或许在遍及应用各处的多个组件中都需要这个设置。因此,将 provider 置于顶层的 App 组件中很有必要。

如此一来在组件树中的任意位置都能访问到该用户设置了。


<!-- src/components/ButtonPrimary.vue -->
<script>
import { inject } from 'vue';
import { UserSettingsStateSymbol } from './ProvideUserSettings';
export default {
  setup() {
    const { theme } = inject(UserSettingsStateSymbol);
    return { theme };
  },
};
</script>
<template>
  <ButtonBase
    :class="$style[`t-${theme}`]"
  >
    <slot/>
  </ButtonBase>
</template>
<style module>
.t-light { /* ... */ }
.t-dark { /* ... */ }
</style>

如上所示,我们已经看到了如何在 inject() 过的上下文中 消费 用户设置状态 了。

接下来的例子中,将演示如何在应用中的任意组件里 更新 该状态:


<!-- src/components/ThemeSwitcher.vue -->
<script>
import { inject } from 'vue';
import { UserSettingsUpdateSymbol } from './ProvideUserSettings';
export default {
  setup() {
    const updateUserSettings = inject(UserSettingsUpdateSymbol);
    const updateTheme = value => updateUserSettings('theme', value);
    return { updateTheme };
  },
};
</script>
<template>
  <div>
    <button @click="updateTheme('dark')">
      Enable darkmode
    </button>
    <button @click="updateTheme('light')">
      Enable lightmode
    </button>
  </div>
</template>

这一次我们通过 UserSettingsUpdateSymbol 来 inject() 得到 provider 中的 update() 函数,并将其包裹在一个新的 updateTheme() 函数中,用来直接设置用户设置对象中的 theme 属性。

当两个按钮之一被点击,用户设置就被更新了,并且 因为该状态是一个反应式对象,所有 inject() 了该状态的组件也都将被更新



相关文章
|
16天前
|
JavaScript 前端开发 IDE
[译] 用 Typescript + Composition API 重构 Vue 3 组件
[译] 用 Typescript + Composition API 重构 Vue 3 组件
[译] 用 Typescript + Composition API 重构 Vue 3 组件
|
9天前
|
存储 API 数据库
如何使用 ef core 的 code first(fluent api)模式实现自定义类型转换器?
本文介绍了如何在 EF Core 的 Code First 模式下使用自定义类型转换器实现 JsonDocument 和 DateTime 类型到 SQLite 数据库的正确映射。通过自定义 ValueConverter,实现了数据类型的转换,并展示了完整的项目结构和代码实现,包括实体类定义、DbContext 配置、Repositories 仓储模式及数据库应用迁移(Migrations)操作。
44 6
如何使用 ef core 的 code first(fluent api)模式实现自定义类型转换器?
|
16天前
|
前端开发 JavaScript API
Vue 3 新特性:在 Composition API 中使用 CSS Modules
Vue 3 新特性:在 Composition API 中使用 CSS Modules
|
14天前
|
容器 Kubernetes Docker
云原生JSF:在Kubernetes的星辰大海中,让JSF应用乘风破浪!
【8月更文挑战第31天】在本指南中,您将学会如何在Kubernetes上部署JavaServer Faces (JSF)应用,享受容器化带来的灵活性与可扩展性。文章详细介绍了从构建Docker镜像到配置Kubernetes部署全流程,涵盖Dockerfile编写、Kubernetes资源配置及应用验证。通过这些步骤,您的JSF应用将充分利用Kubernetes的优势,实现自动化管理和高效运行,开启Java Web开发的新篇章。
28 0
|
14天前
|
负载均衡 监控 JavaScript
探索微服务架构下的API网关模式
【8月更文挑战第31天】在微服务的大潮中,API网关不仅是流量的守门人,更是服务间通信的桥梁。本文将带你深入理解API网关的核心概念、设计要点及其在微服务架构中的重要作用,同时通过代码示例揭示如何利用API网关提升系统的灵活性与扩展性。
|
14天前
|
存储 JavaScript 前端开发
探索React状态管理:Redux的严格与功能、MobX的简洁与直观、Context API的原生与易用——详细对比及应用案例分析
【8月更文挑战第31天】在React开发中,状态管理对于构建大型应用至关重要。本文将探讨三种主流状态管理方案:Redux、MobX和Context API。Redux采用单一存储模型,提供预测性状态更新;MobX利用装饰器语法,使状态修改更直观;Context API则允许跨组件状态共享,无需第三方库。每种方案各具特色,适用于不同场景,选择合适的工具能让React应用更加高效有序。
27 0
|
14天前
|
前端开发 API
React 中 Context 的概念
【8月更文挑战第31天】
19 0
|
15天前
|
JavaScript 前端开发 API
Vue.js 3.x新纪元:Composition API引领潮流,Options API何去何从?前端开发者必看的抉择指南!
【8月更文挑战第30天】Vue.js 3.x 引入了 Composition API,为开发者提供了更多灵活性和控制力。本文通过示例代码对比 Composition API 与传统 Options API 的差异,帮助理解两者在逻辑复用、代码组织、类型推断及性能优化方面的不同,并指导在不同场景下的选择。Composition API 改善了代码可读性和维护性,尤其在大型项目中优势明显,同时结合 TypeScript 提供更好的类型推断和代码提示,减少错误并提升开发效率。尽管如此,在选择 API 时仍需考虑项目复杂性、团队熟悉度等因素。
30 0
|
16天前
|
前端开发 知识图谱
[译] React 中的 "最新 Ref 模式"
[译] React 中的 "最新 Ref 模式"
|
30天前
|
机器人 API Python
智能对话机器人(通义版)会话接口API使用Quick Start
本文主要演示了如何使用python脚本快速调用智能对话机器人API接口,在参数获取的部分给出了具体的获取位置截图,这部分容易出错,第一次使用务必仔细参考接入参数获取的位置。