文章同步在大众号:萌萌哒草头将军,欢迎重视!

今日的论题是两种常见的规划形式:上下文形式和依靠注入形式。

这两种不同的规划形式,一般用于软件体系中完成组件之间的数据共享和依靠办理。作为耳熟能详的常见功用,这儿就不详细展开定义了,咱们单纯的从运用视点去解读他们的区别。

他们一般在跨组件通信中被说到,比方,React、Svelte、SolidJS都用了Context上下文形式,Vue、Angular中运用了依靠注入形式。

如安在Vue3中运用上下文形式,在React中运用依靠注入形式

但是稍微了解下就知道,同样是Context上下文形式,React的实践又与Svelte、SolidJS的完成不相同。这是因为规划形式的完成是要紧贴体系场景的需求,才干被称为优秀的规划形式。

下面是我的一些实践。

Vue3中运用上下文形式

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

接下来,咱们先完成一个基础版的上下文形式:

// 创立上下文对象
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中运用,咱们需求简略的本地化改造。

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;

此时,咱们只需求在组件中运用了:

// store.js
import createContext from './context';
export const { getContext, setContext } = createContext({a: 1})
// Children.vue
<template>
  <div>{{ context.a }}</div>
</template>
<script setup lang='ts'>
import {getContext} from './store/context';
const context = getContext()
</script>
// 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中运用依靠注入形式

咱们已经为Vue3完成了相似React相似的上下文形式。

React中运用依靠注入

留意:同理。这是一个外部体系。

接下来,咱们在完成一个基础版的依靠注入形式

// 依靠注入容器
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完成依靠注入功用。

为了能够将需求的数据注入到组件中,咱们需求在此基础上供给一个高阶组件将数据注入到其间:

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组件中运用了。

// Other.jsx
import { inject } from "./inject"
const Ohther = (props) => {
  return <div>{ props.name }</div>;
}
export default inject(Ohther, ['name'])
// App.jsx
import { injectDependency } from "./inject";
import Ohther from "./Ohther";
injectDependency('name', '萌萌哒草头将军');
function App() {
  return (
    <div>
      <h3>大众号:萌萌哒草头将军</h3>
      <Ohther />
    </div>
  )
}
export default App;

如安在Vue3中运用上下文形式,在React中运用依靠注入形式

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

在注入的时分,也需求供给mapper方法,这样就更加高雅了。

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表达式、函数等,希望能够根据实际情况灵活的运用它们。

好了今日的论题就这些,希望能够帮助各位小伙伴,感谢您的阅览,