Why ioc containers for Vue3
Vue3 is perfectly suited for the development of large-scale business systems due to its excellent responsive system, as well as its convenient functionality features. However, we not only need to be able to do it, but we need to do it better. The key to large business systems is decoupling, thus slowing down the growth of shi mountain code. And ioc containers are the best decoupling tool available. angular introduced ioc containers from the beginning, so it has been leading the way in business engineering and has been beckoning to other front-end frameworks: "I'll wait for you in the front, hope to see you again in three years". So, I'll try to take two steps forward, introduce ioc containers in Vue3, and use that to expand other engineering capabilities and get a new framework:Zova.. Feel free to tap and share whether you think it works well or not:
IOC Container Classification
There are two types of ioc containers in Zova.
-
Global ioc container
: The only global ioc container is automatically created when the system is initialized. Bean instances created in this container are in singleton mode -
Component Example ioc Container
: When creating Vue component instances, the system creates an ioc container for each Vue component instance. Bean instances created in this container can share data and logic within the scope of the component instance.
Bean Class Classification
There are two types of Bean Classes in Zova:
-
Anonymous bean
: Use@Local
The decorated class isAnonymous bean
This type of bean is only used within a module, and there are no naming conflicts. This type of bean is only used inside modules, so there are no naming conflicts, and it's easy to define and use. -
named bean
: In addition to@Local
The class decorated by all decorator functions exceptnamed bean
Zova provides a naming convention for such beans to avoid naming conflicts and to facilitate cross-module usage.
Injection mechanism
Adopted by Zova@Use
Decorator functions inject bean instances and provide several injection mechanisms:
1. Bean Class
pass (a bill or inspection etc)Bean Class
Finds and injects a Bean instance in the ioc container and creates it automatically if it does not exist. This mechanism is typically used inco-module injection
import { ModelTodo } from '../../bean/';
class ControllerTodo {
@Use()
$$modelTodo: ModelTodo;
}
2. Bean identification
pass (a bill or inspection etc)Bean identifier
Finds and injects a Bean instance in the ioc container and creates it automatically if it does not exist. This mechanism is typically used incross-module injection
respond in singingcascade injection
import type { ModelTabs } from 'zova-module-a-tabs';
class ControllerLayout {
@Use('')
$$modelTabs: ModelTabs;
}
- pass (a bill or inspection etc)
Finding and Injecting Bean Instances
- Therefore, it is only necessary to import the type type of ModelTabs, thus maintaining a loosely coupled relationship between the modules
3. Registered name
pass (a bill or inspection etc)registered name
Finds and injects a Bean instance in the ioc container and returns null if it does not exist. This mechanism is typically used inco-module injection
cap (a poem)cascade injection
import type { ModelTodo } from '../../bean/';
class ControllerTodo {
@Use({ name: '$$modelTodo' })
$$modelTodo: ModelTodo;
}
- By registered name
$$modelTodo
Finds and injects a Bean instance. In general, you should make sure that the bean instance has been injected beforehand in the ioc container, otherwise it will return null values
4. Attribute names
pass (a bill or inspection etc)property name
Finds and injects a Bean instance in the ioc container and returns null if it does not exist. This mechanism is typically used inco-module injection
cap (a poem)cascade injection
import type { ModelTodo } from '../../bean/';
class ControllerTodo {
@Use()
$$modelTodo: ModelTodo;
}
- By attribute name
$$modelTodo
Finds and injects a Bean instance. In general, you should make sure that the bean instance has been injected beforehand in the ioc container, otherwise it will return null values
Injection range
Anonymous bean
The default injection scopes for allctx
,named bean
The default injection scope can be specified at the time of definition, and different scenes have different default injection scopes. In addition, you can specify the default scope of injection in @Use through thecontainerScope
option overrides the default injection scope
Zova offers the following injection scopes:app/ctx/new/host/skipSelf
1. app
If the scope of the injection is an app, then the bean instance is injected in the global ioc container, thus achieving a singleton effect
// in module: test-module1
@Store()
class StoreCounter {}
// in module: test-module2
import type { StoreCounter } from 'zova-module-test-module1';
class Test {
@Use('')
$$storeCounter: StoreCounter;
}
- The Store's injection scope is the app by default, so it is identified by the bean
Finding and injecting bean instances in the global ioc container
2. ctx
If the injection scope is ctx, then inject the bean instance in the ioc container of the current component instance
// in module: a-tabs
@Model()
class ModelTabs {}
// in module: test-module2
import type { ModelTabs } from 'zova-module-a-tabs';
class ControllerLayout {
@Use('')
$$modelTabs: ModelTabs;
}
- The Model's injection scope is by default the ctx, so it is identified by the bean.
Finds and injects a bean instance in the ioc container of the current component instance
3. new
If the scope of the injection is new, then a new bean instance is created directly
// in module: a-tabs
@Model()
class ModelTabs {}
// in module: test-module2
import type { ModelTabs } from 'zova-module-a-tabs';
class ControllerLayout {
@Use({ beanFullName: '', containerScope: 'new' })
$$modelTabs: ModelTabs;
}
- Since the containerScope option is specified as new, the containerScope is identified by the bean.
Create a new bean instance directly
cascade injection
The injection range is in addition to the support forapp/ctx/new
, also supports hierarchical injection:host/skipSelf
4. host
If the injection scope is host, then find and inject the bean instance in the ioc container of the current component instance and all parent containers in turn, returning null if it does not exist
// in parent component
import type { ModelTabs } from 'zova-module-a-tabs';
class Parent {
@Use('')
$$modelTabs: ModelTabs;
}
// in child component
import type { ModelTabs } from 'zova-module-a-tabs';
class Child {
@Use({ containerScope: 'host' })
$$modelTabs: ModelTabs;
}
- Since the parent component has already injected a bean instance of ModelTabs, the child component can directly find and inject the
-
cascade injection
All injection mechanisms are also supported:Bean Class/Bean Identifier/Registered Name/Property Name
5. skipSelf
If the scope of the injection is skipSelf, then find and inject the bean instance in all parent containers in turn, and return null if it doesn't exist
Zova is open source:/cabloy/zova