如何在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表达式、函数等,希望可以根据实际情况灵活的使用它们。

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

相关推荐
Csvn4 小时前
OpenSpec 详细使用教程
前端
之歆4 小时前
Day19_LESS 完全指南——从入门到工程实践
前端·css·less
云水一下5 小时前
HTML5 从入门到精通:实战收官——从零搭建完整静态网站,综合运用所有知识
前端·html5
不总是5 小时前
Windows 系统 Node.js 免安装版(zip)安装与配置教程(2026 最新)
前端·windows·node.js
冬奇Lab5 小时前
每日一个开源项目(第105篇):Twenty - 跳出 Salesforce 的圈套,定义现代开源 CRM
前端·后端·开源
zhangyao9403306 小时前
开发pc端时,表格的高度怎么设置才能铺满页面
前端·javascript·elementui
kjs--7 小时前
浏览器书签执行脚本
前端
之歆7 小时前
Day16_JavaScript 轮播图与事件工程实战(下篇)
服务器·开发语言·前端·javascript·网络·性能优化
沄媪7 小时前
CSRF 跨站请求伪造
前端·ctf·csrf
kyriewen8 小时前
我关掉了Copilot:因为我写的代码出现在了别人的建议里
前端·javascript·ai编程