笔者目前是一个 Vue.js 和 React 都在用的前端打工人,像 Vue Composition API 和 React Hooks 这些技术真的是援救人生啊,感觉前端的开发体验越来越像丝绸般顺滑。

另一方面呢,因为目前的我的项目外面有着非常复杂的数据处理逻辑,所以咱们封装了很多可复用的 Service 类。然而有一点不太不便的是,必须在业务组件或者 Service 外面手动创立它们所依赖的 Service 实例。受 Angular、Nest 以及 Spring 这些框架的启发,开始尝试在 Vue.js 和 React 利用中通过依赖注入的形式解决这个问题。

Vesselize (文档:vesselize.js.org)就是笔者最近业余时间写的一个 JavaScript IoC 容器,目前曾经在我的项目中正式应用。能够间接在 Vue.js 或 React 利用中,间接通过相似 useInstance('ServiceName') 的 API 来解决对服务实例的依赖。这次造轮子的过程中学到了不少新常识,分享进去心愿对大家有所帮忙。

上面的内容是它的基本概念级入门指南。

Vesselize 外围概念

Providers

Provider 通常是能够被实例化的 JavaScript 结构器函数,此外也能够是任意的工厂办法及曾经申明好的值。它们会被注册到容器外面,用于依赖注入及查找。

Container

Container 的职责是用于初始化实例并解决他们的依赖关系。

Context

默认状况下,容器创立的实例都是单例的。通过指定一个 Context 对象,咱们能够创立一个跟该上下文绑定的实例。

Vue.js 利用集成 Vesselize 入门指南

上面咱们通过代码的模式展现如何在 Vue.js 利用中集成 Vesselize。

装置

yarn add @vesselize/vue# ORnpm i @vesselize/vue复制代码

创立 Providers

假如利用中须要以下三个服务:

  • UserAPI 用于申请接口数据
  • UserService 调用 UserAPI 获取数据并进行业务逻辑的解决
  • AuthService 用于判断用户的角色,比方是否为管理员
// file: api/UserAPI.jsclass UserAPI {  async fetchUser(id) {    return fetch(`/path/to/user/${id}`).then(res => res.json());  }}// file: services/UserService.jsclass UserService {  userAPI = null;  async getUser(id) {    const user = await this.userAPI.fetchUser(id);            // 数据处理逻辑...            return user;  }        // 通过 Vesselize 容器注入 userAPI 实例  setVesselize(vesselize) {    this.userAPI = vesselize.get('UserAPI');  }}// file: services/AuthService.jsclass AuthService {  constructor(maxAdminUserId) {    this.maxAdminUserId = maxAdminUserId;  }  isAdmin(user) {    return user.id <= this.maxAdminUserId;  }}复制代码

创立 VueVesselize 插件

上面的代码通过 createVesselize 办法创立 Vue.js 插件,同时它也是一个容器实例。

import { createVesselize } from '@vesselize/vue';import UserAPI from './api/UserAPI';import UserService from './services/UserService';import RoleAuthService from './services/RoleAuthService';const vesselize = createVesselize({  providers: [    {      token: 'UserAPI',      useClass: UserAPI    },    {      token: 'UserService',      useClass: UserService    },    {      token: 'AuthService',      useFactory() {        const maxAdminUserId = 1;        return new AuthService(maxAdminUserId);      }    }  ]});复制代码

注册 VueVesselize 插件

import { createApp } from 'vue';import router from './router';import store from './store';import vesselize from './vesselize';import App from './App.vue';const app = createApp(App)  .use(store)  .use(router)  .use(vesselize);app.mount('#app');复制代码

在组件中获取服务实例

通过 useInstance 这个 Composition API,咱们能够在组件中很不便地获取组件实例。

<template>  <div>Profile</div>  <p>{{ JSON.stringify(user) }}</p>  <p>Role: {{ isAdmin ? 'Administrator' : 'User' }}</p></template><script> import { computed, ref, watchEffect } from 'vue';import { useRoute } from 'vue-router';import { useInstance } from '@vesselize/vue';export default {  setup() {    const route = useRoute();    const userId = computed(() => route.params.id);    const user = ref({});    const isAdmin = ref(false);    // 通过 Vue Composition API 获取组件实例    const userService = useInstance('UserService');    const authService = useInstance('AuthService');    watchEffect(() => {      if (userId.value) {        userService.getUser(userId.value).then((data) => {          user.value = data;          isAdmin.value = authService.isAdmin(data);        });      }    });    return {      user,      isAdmin,    };  },}; </script>复制代码

最初,如果你想间接在我的项目中尝试,能够看一下这个示例我的项目:vesselize-vue-starter.

React 利用集成 Vesselize 入门指南

还是下面的例子,咱们看一下如何在 React 中实现。

装置

yarn add @vesselize/react# ORnpm i @vesselize/react复制代码

创立 Providers

与下面一样也是须要 UserAPI, UserService, AuthService 三个服务。

组合 Providers

咱们先将所有的 Provider 组合为一个数组:

import UserAPI from './api/UserAPI';import UserService from './services/UserService';import RoleAuthService from './services/RoleAuthService';const providers = [  {    token: 'UserAPI',    useClass: UserAPI  },  {    token: 'UserService',    useClass: UserService  },  {    token: 'AuthService',    useFactory() {      const maxAdminUserId = 1;      return new AuthService(maxAdminUserId);    }  }];export default providers;复制代码

增加组件 VesselizeProvider

通过 Vesselize 提供的 VesselizeProvider 来包裹我的项目的 App 组件,同时传入组合好的所有 Provider。

import { VesselizeProvider } from '@vesselize/react';import providers from './providers';import UserProfile from './components/UserProfile';function App() {  return (    <VesselizeProvider providers={providers}>      <UserProfile />    </VesselizeProvider>  );}export default App;复制代码

在组件中获取服务实例

通过 useInstance 这个 hook, 能够十分便捷地获取到服务实例。

import { useParams }  from 'react-router-dom'import { useState, useEffect } from 'react';import { useInstance } from '@vesselize/react';function UserProfile() {  const { id } = useParams();  const [user, setUser] = useState({});  const [isAdmin, setIsAdmin] = useState(false);  // 通过 hook 获取组件实例  const userService = useInstance('UserService');  const authService = useInstance('AuthService');  useEffect(() => {    userService.getUser(id).then((data) => {      setUser(data);      setIsAdmin(authService.isAdmin(data));    });  }, [id, userService, authService]);  return (    <div>      <span>{JSON.stringify(user)}</span>      <p>Role: {isAdmin ? 'Administrator' : 'User'}</p>    </div>  );}export default UserProfile;复制代码

最初,如果你想间接在我的项目中尝试,能够看一下这个通过 create-react-app 创立的示例我的项目: vesselize-react-starter.

写在最初

在发明 Vesselize 的过程中,我学习到了很多货色。本文将它分享进去,也心愿对你有所帮忙。

感激你的浏览,祝你生存欢快!

附录

Github 代码仓库: github.com/vesselize

文档及使用指南: vesselize.js.org

我的项目示例:

  • vesselize-vue-starter
  • vesselize-react-starter