如何在Vue3中使用上下文模式,在React中使用依赖注入模式🚀🚀🚀

文章同步在公众号:萌萌哒草头将军,欢迎关注!

今天的话题是两种常见的设计模式:上下文模式和依赖注入模式。

这两种不同的设计模式,通常用于软件系统中实现组件之间的数据共享和依赖管理。作为耳熟能详的常见功能,这里就不详细展开定义了,我们单纯的从使用角度去解读他们的区别。

他们通常在跨组件通信中被提到,比如,React、Svelte、SolidJS都用了Context上下文模式,Vue、Angular中使用了依赖注入模式。

但是稍微了解下就知道,同样是Context上下文模式,React的实践又与Svelte、SolidJS的实现不相同。这是因为设计模式的实现是要紧贴系统场景的需求,才能被称为优秀的设计模式。

下面是我的一些实践。

🚀 Vue3中使用上下文模式

注意:这不是依赖Vue组件层级树的上下文。React的上下文系统是依赖于组件层级树的。换句话说。这是一个外部系统。

接下来,我们先实现一个基础版的上下文模式:

js 复制代码
// 创建上下文对象
function createContext(initialValue) {
  // 初始值
  let value = initialValue; 
  function getContext() {
    // 返回当前上下文值
    return value;
  }
  function setContext(newValue) {
    // 更新上下文值
    value = newValue;
  }
  return {
    getContext,
    setContext
  };
}

// 上下文提供者
const myContext = createContext("Hello");
// 上下文消费者
function myConsumer() {
  const contextValue = myContext.getContext();
  console.log(contextValue);
}
// 使用示例
myConsumer(); // 输出: "Hello"
myContext.setContext("World"); // 更新上下文值
myConsumer(); // 输出: "World"

如果这个上下文模式要想在Vue中使用,我们需要简单的本地化改造。

js 复制代码
import { reactive } from "vue";

// 创建上下文对象
function createContext(initialValue) {
  // 初始值
  const value = reactive(initialValue)
  function getContext() {
    // 返回当前上下文值
    return value;
  }
  function setContext(key, newValue) {
    // 更新上下文值
    value[key] = newValue;
  }
  return {
    getContext,
    setContext
  };
}

export default createContext;

此时,我们只需要在组件中使用了:

js 复制代码
// store.js
import createContext from './context';
export const { getContext, setContext } = createContext({a: 1})
html 复制代码
// Children.vue
<template>
  <div>{{ context.a }}</div>
</template>
  
<script setup lang='ts'>
import {getContext} from './store/context';
const context = getContext()
</script>
html 复制代码
// App.vue
<script setup lang="ts">
import Children from "./Children.vue"
import {setContext} from './store.js';
</script>

<template>
  <h4>公众号:萌萌哒草头将军</h4>
  <button @click="setContext('a', Math.random())">change</button>
  <Context />
</template>

我们已经为Vue3实现了类似React类似的上下文模式。

🚀 React中使用依赖注入

注意:同理。这是一个外部系统。

接下来,我们在实现一个基础版的依赖注入模式

js 复制代码
// 依赖注入容器
const dependences = {};

// 注册依赖项
function injectDependency(key, dependency) {
  dependences[key] = dependency;
}

// 解析依赖项
function resolveDependency(key) {
  if (dependences[key]) {
    return dependences[key];
  } else {
    throw new Error(`Dependency '${key}' not found.`);
  }
}

// 使用示例
// 注册依赖项
registerDependency('userService', { name: 'John', age: 30 });

// 解析依赖项
const userService = resolveDependency('userService');
console.log(userService); // 输出: { name: 'John', age: 30 }

接下来,我们为react实现依赖注入功能。

为了可以将需要的数据注入到组件中,我们需要在此基础上提供一个高阶组件将数据注入到其中:

js 复制代码
import React from "react";

const dependencies = {}

export function injectDependency(key, dependency) {
  dependencies[key] = dependency
}

// 解析依赖项
export function resolveDependency(key) {
  if (dependencies[key]) {
    return dependencies[key];
  } else {
    throw new Error(`Dependency '${key}' not found.`);
  }
}

export function inject(Component, deps, mapper) {
  return class Injector extends React.Component {
    constructor(props) {
      super(props);
      this.dependencies = {};
      deps.forEach(key => {this.dependencies[key] = dependencies[key]})
    }
    render() {
      return (
        <Component
          {...this.state}
          {...this.props}
          {...this._resolvedDependencies}
        />
      );
    }
  };
}

接着我们就可以直接在React组件中使用了。

js 复制代码
// Other.jsx
import { inject } from "./inject"

const Ohther = (props) => {
  return <div>{ props.name }</div>;
}

export default inject(Ohther, ['name'])
js 复制代码
// App.jsx
import { injectDependency } from "./inject";
import Ohther from "./Ohther";

injectDependency('name', '萌萌哒草头将军');

function App() {
  return (
    <div>
      <h3>公众号:萌萌哒草头将军</h3>
      <Ohther />
    </div>
  )
}

export default App;

很棒,我们做到了。不过还是不如vue那么优雅,所以,我们稍微改造下:

在注入的时候,也需要提供mapper方法,这样就更加优雅了。

js 复制代码
export function inject(Component, deps, mapper) {
  return class Injector extends React.Component {
    constructor(props) {
      super(props);
      this.dependencies = mapper(...deps.map(resolveDependency));
    }
    render() {
      return (
        <Component
          {...this.state}
          {...this.props}
          {...this.dependencies}
        />
      );
    }
  };
}

// 注入的时候注意提供了mapper方法
export default inject(Ohther, ['name'], name => ({ name })

依赖注入其实是个很热门的话题,常常还会提到控制反转,不过这不是今天的话题。这里想说的是,在前端注入外部信息,可以提高代码的复用性和组件的灵活性,上面的示例中注入的仅仅是个字符串,理论上,还可以是jsx表达式、函数等,希望可以根据实际情况灵活的使用它们。

好了今天的话题就这些,希望可以帮助各位小伙伴,感谢您的阅读,

相关推荐
EnCi Zheng13 分钟前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen17 分钟前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技18 分钟前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人29 分钟前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实29 分钟前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha40 分钟前
三目运算符
linux·服务器·前端
晓晨的博客1 小时前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
donecoding1 小时前
别再让 pnpm 跟着 nvm 跑了!独立安装终极指南
前端·node.js·前端工程化
GISer_Jing1 小时前
AI全栈转型_TS后端学习路线
前端·人工智能·后端·学习