Vue3 与依赖注入

Vue3 与依赖注入

本文写于 2021 年 2 月 19 日html

在 React 中,咱们能够经过 context 与 useContext 实现单例、注入……等诸多特性。vue

详细请看上一篇文章:如何利用 React Hooks 管理全局状态.dom

例如:ide

const SomeService = createContext(null);

const useRootSomeService = () => {
  const [n, setN] = useState(0);

  const add = useCallback(() => {
    setN((number) => number + 1);
  }, []);

  return { n, setN };
};

const App: React.FC = () => {
  return (
    <SomeService.Provider value={useRootSomeService()}>
      <Apple />
    </SomeService>
  )
};

const Apple: React.FC = () => {
  const someService = useContext(SomeService)
};

那么 Vue3 能够吗?this

能够!!!只须要利用 Vue3 的 provide 与 inject API 即。code

建立一个 Service

import { Ref, ref } from "vue";

class ChatService {
  static INJECT_KEY: string;

  conversations: Ref<Conversation[]>;

  constructor() {
    this.conversations = ref([]);
  }
}

这样咱们只须要在组件中实例化该 class,就能够拥有响应性的 conversations 属性了。htm

可是咱们不知足于如此,咱们还想要在任何地方,均可以使用 const chatService = inject(ChatService); 来拿到服务的单例!blog

provide/inject

vue3 提供给咱们的 provide API 能够在任意组件中使用:provide(key, variable);get

使用后该组件的自组件的任何位置均可以利用 inject API 拿到刚刚注入的变量:const v = inject(key);string

所以咱们能够这么封装一下:

import { provide as vueProvide, inject as vueInject } from "vue";

export const createInjectKey = () => {
  const randomNumber = Math.round(Math.random() * 10 ** 8).toString();
  return randomKey;
};

interface ServiceType<T> {
  new (): T;
  INJECT_KEY: string;
}

export function provide<T>(Service: ServiceType<T>) {
  const key = createInjectKey();
  Service.INJECT_KEY = key;
  vueProvide(key, new Service());
}

export function inject<T>(Service: ServiceType<T>): T {
  const service = vueInject<T>(Service.INJECT_KEY);
  if (!service) {
    console.error("You have to provide service first!!!");
  }
  return service!;
}

这样一来,咱们只须要写一个拥有 static INJECT_KEY 属性的 class,就能够在组件树顶端使用 provide(xxxService),而后再在任意位置调用 inject(xxxService) 来获取服务单例了!

(完)

相关文章
相关标签/搜索