笔者目前是一个 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
# OR
npm i @vesselize/vue
创建 Providers
假设应用中需要以下三个服务:
UserAPI
用于请求接口数据UserService
调用 UserAPI 获取数据并进行业务逻辑的处理AuthService
用于判断用户的角色,比如是否为管理员
// file: api/UserAPI.js
class UserAPI {
async fetchUser(id) {
return fetch(`/path/to/user/${id}`).then(res => res.json());
}
}
// file: services/UserService.js
class 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.js
class 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
# OR
npm 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
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!