为什么要为Vue3提供ioc容器
Vue3因其出色的响应式系统,以及便利的功能特性,完全胜任大型业务系统的开发。但是,我们不仅要能做到,而且要做得更好。大型业务系统的关键就是解耦合,从而减缓shi山代码的生长。而ioc容器是目前最好的解耦合工具。Angular从一开始就引入了ioc容器,因此在业务工程化方面一直处于领先地位,并且一直在向其他前端框架招手:“我在前面等你们,希望三年后能再见”。那么,我就试着向前走两步,在Vue3中引入ioc容器,并以此为基础扩充其他工程能力,得到一个新框架:Zova。诸君觉得是否好用,欢迎拍砖、交流:
IOC容器分类
在 Zova 中有两类 ioc 容器:
全局ioc容器
:在系统初始化时,会自动创建唯一一个全局 ioc 容器。在这个容器中创建的Bean实例都是单例模式组件实例ioc容器
:在创建 Vue 组件实例时,系统会为每一个 Vue 组件实例创建一个 ioc 容器。在这个容器中创建的Bean实例可以在组件实例范围之内共享数据和逻辑
Bean Class分类
Zova 采用模块化体系,Bean Class 都由不同的模块提供。使用模块内部的 Bean Class 时可以直接基于Class类型
定位。在跨模块使用时可以基于Bean标识
定位,而不是基于Class类型/文件路径
定位,这样有利于实现模块之间的松耦合
因此,Zova 提供了两类 Bean Class:
匿名bean
:使用@Local
装饰的 class 就是匿名bean
。此类 bean 仅在模块内部使用,不存在命名冲突的问题,定义和使用都很便捷具名bean
:除了@Local
之外,其他装饰器函数装饰的 class 都是具名bean
。Zova 为此类 bean 提供了命名规范,既可以避免命名冲突,也有利于跨模块使用
注入机制
Zova 通过@Use
装饰器函数注入 Bean 实例,提供了以下几种注入机制:
1. Bean Class
通过Bean Class
在 ioc 容器中查找并注入 Bean 实例,如果不存在则自动创建。这种机制一般用于同模块注入
import { ModelTodo } from '../../bean/model.todo.js';
class ControllerTodo {
@Use()
$$modelTodo: ModelTodo;
}
2. Bean标识
通过Bean标识
在 ioc 容器中查找并注入 Bean 实例,如果不存在则自动创建。这种机制一般用于跨模块注入
和层级注入
import type { ModelTabs } from 'zova-module-a-tabs';
class ControllerLayout {
@Use('a-tabs.model.tabs')
$$modelTabs: ModelTabs;
}
- 通过
a-tabs.model.tabs
查找并注入 Bean 实例 - 因此,只需导入 ModelTabs 的 type 类型,从而保持模块之间的松耦合关系
3. 注册名
通过注册名
在 ioc 容器中查找并注入 Bean 实例,如果不存在则返回空值。这种机制一般用于同模块注入
和层级注入
import type { ModelTodo } from '../../bean/model.todo.js';
class ControllerTodo {
@Use({ name: '$$modelTodo' })
$$modelTodo: ModelTodo;
}
- 通过注册名
$$modelTodo
查找并注入 Bean 实例。一般而言,应该确保在 ioc 容器中已经事先注入过 Bean 实例,否则就会返回空值
4. 变量名
通过变量名
在 ioc 容器中查找并注入 Bean 实例,如果不存在则返回空值。这种机制一般用于同模块注入
和层级注入
import type { ModelTodo } from '../../bean/model.todo.js';
class ControllerTodo {
@Use()
$$modelTodo: ModelTodo;
}
- 通过变量名
$$modelTodo
查找并注入 Bean 实例。一般而言,应该确保在 ioc 容器中已经事先注入过 Bean 实例,否则就会返回空值
注入范围
匿名bean
的默认注入范围都是ctx
,具名bean
可以在定义时指定默认注入范围,不同的场景(scene)有不同的默认注入范围。 此外,在实际注入时,还可以在@Use 中通过injectionScope
选项覆盖默认的注入范围
Zova 提供了以下几种注入范围:app/ctx/new/host/skipSelf
1. app
如果注入范围是 app,那么就在全局 ioc 容器中注入 bean 实例,从而实现单例的效果
// in module: test-module1
@Store()
class StoreCounter {}
// in module: test-module2
import type { StoreCounter } from 'zova-module-test-module1';
class Test {
@Use('test-module1.store.counter')
$$storeCounter: StoreCounter;
}
- Store 的注入范围默认是 app,因此通过 Bean 标识
test-module1.store.counter
在全局 ioc 容器中查找并注入 bean 实例
2. ctx
如果注入范围是 ctx,那么就在当前组件实例的 ioc 容器中注入 bean 实例
// in module: a-tabs
@Model()
class ModelTabs {}
// in module: test-module2
import type { ModelTabs } from 'zova-module-a-tabs';
class ControllerLayout {
@Use('a-tabs.model.tabs')
$$modelTabs: ModelTabs;
}
- Model 的注入范围默认是 ctx,因此通过 Bean 标识
a-tabs.model.tabs
在当前组件实例的 ioc 容器中查找并注入 bean 实例
3. new
如果注入范围是 new,那么就直接创建新的 bean 实例
// in module: a-tabs
@Model()
class ModelTabs {}
// in module: test-module2
import type { ModelTabs } from 'zova-module-a-tabs';
class ControllerLayout {
@Use({ beanFullName: 'a-tabs.model.tabs', injectionScope: 'new' })
$$modelTabs: ModelTabs;
}
- 由于指定 injectionScope 选项为 new,因此通过 Bean 标识
a-tabs.model.tabs
直接创建新的 bean 实例
层级注入
注入范围除了支持app/ctx/new
,还支持层级注入:host/skipSelf
4. host
如果注入范围是 host,那么就在当前组件实例的 ioc 容器以及所有父容器中依次查找并注入 bean 实例,如果不存在则返回空值
// in parent component
import type { ModelTabs } from 'zova-module-a-tabs';
class Parent {
@Use('a-tabs.model.tabs')
$$modelTabs: ModelTabs;
}
// in child component
import type { ModelTabs } from 'zova-module-a-tabs';
class Child {
@Use({ injectionScope: 'host' })
$$modelTabs: ModelTabs;
}
- 由于父组件已经注入了 ModelTabs 的 bean 实例,因此子组件可以直接查找并注入
层级注入
同样支持所有注入机制:Bean Class/Bean标识/注册名/变量名
5. skipSelf
如果注入范围是 skipSelf,那么就在所有父容器中依次查找并注入 bean 实例,如果不存在则返回空值
Zova已开源:https://github.com/cabloy/zova
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容