Location>code7788 >text

Way to go, an Angular-rivaling ioc container for Vue3!

Popularity:553 ℃/2024-07-31 17:02:33

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.

  1. 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
  2. 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:

  1. Anonymous bean: Use@LocalThe decorated class isAnonymous beanThis 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.
  2. named bean: In addition to@LocalThe class decorated by all decorator functions exceptnamed beanZova provides a naming convention for such beans to avoid naming conflicts and to facilitate cross-module usage.

Injection mechanism

Adopted by Zova@UseDecorator functions inject bean instances and provide several injection mechanisms:

1. Bean Class

pass (a bill or inspection etc)Bean ClassFinds 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 identifierFinds 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 injectionrespond 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 nameFinds and injects a Bean instance in the ioc container and returns null if it does not exist. This mechanism is typically used inco-module injectioncap (a poem)cascade injection

import type { ModelTodo } from '../../bean/';

class ControllerTodo {
  @Use({ name: '$$modelTodo' })
  $$modelTodo: ModelTodo;
}
  • By registered name$$modelTodoFinds 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 nameFinds and injects a Bean instance in the ioc container and returns null if it does not exist. This mechanism is typically used inco-module injectioncap (a poem)cascade injection

import type { ModelTodo } from '../../bean/';

class ControllerTodo {
  @Use()
  $$modelTodo: ModelTodo;
}
  • By attribute name$$modelTodoFinds 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 beanThe default injection scopes for allctxnamed beanThe 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 thecontainerScopeoption 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 beanFinding 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 injectionAll 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