Four types of global state data
In actual development, you will encounter four types of global state data: asynchronous data (usually from the server)
and synchronous data
, while synchronous data
is divided into three types: localstorage
, cookie
, and memory
. In the traditional Vue3, different mechanisms are used to handle these state data, while only a unified Model
mechanism is needed in Zova
Global State Data | Traditional Vue3 | Zova |
---|---|---|
asynchronous data | Pinia | Model |
localstorage | Pinia + Localstorage | Model |
cookie | Pinia + Cookie | Model |
memory | Pinia | Model |
By using the Model
mechanism to uniformly manage these global state data, some common system capabilities can be provided, including Memory Optimization
, Persistence
and SSR Support
, etc., thereby standardizing data usage, simplifying code structure, and improving code maintainability
Feature 1. Support for async data and sync data
The base of Zova Model is TanStack Query. TanStack Query
provides powerful data acquisition, caching and update capabilities. If you have not used similar data management mechanisms like TanStack Query, it is strongly recommended that you learn about it, and you will definitely be impressed by the thought
The core of TanStack Query is to manage asynchronous data (usually from the server)
. Zova provides some extension capabilities based on TanStack Query, so as to support the management of synchronous data
. In other words, all the features and capabilities described below apply to both asynchronous data
and synchronous data
Feature 2. Automatic caching
Locally cache the acquired asynchronous data to avoid repeated acquisition. For synchronous data, read and write operations will be automatically performed on localstorage or cookie
Feature 3. Automatic update
Provide data expiration strategy and automatically update at the right time
Feature 4. Reduce duplicate requests
When accessing data in multiple places in the program at the same time, the server API will only be called once. If it is synchronous data, only one operation will be called for localstorage or cookie
Feature 5. Memory optimization
Although the data managed by Zova Model is in a global state, it does not always occupy memory, but provides a mechanism for memory release and recycling. Specifically, it is to create cache data according to business needs when creating a Vue component instance, release the reference to the cache data when the Vue component instance is unmounted, and if no reference and expiration time reached, the garbage collection mechanism (GC) will be triggered to complete the release of memory, thereby saving memory usage. This has significant benefits for large projects and scenarios where users need to interact with the interface for a long time
Feature 6. Persistence
Local cache can be persisted and can be automatically restored when the page is refreshed to avoid server requests. If it is asynchronous data, it will be automatically persisted to IndexDB
to meet the storage needs of large amounts of data. If it is synchronous data, it will be automatically persisted to localstorage
or cookie
Memory optimization
and persistence
work together, and the effect is more obvious for large projects. For example, the data obtained from the server will generate a local cache and automatically persist. When no longer used and expires, the local cache will be automatically destroyed to release memory. When the data is accessed again, the local cache data will be automatically restored from persistence instead of requesting the data from the server again
Feature 7. SSR support
Different types of state data will also have different implementation mechanisms in SSR mode. Zova Model smoothes out the differences in these state data and uses a unified mechanism to hydrate them, making the implementation of SSR more natural and intuitive, significantly reducing the mental burden
Feature 8. Automatic namespace isolation
Zova manages data through Model Bean. The Bean itself has a unique identifier and can be used as a namespace for data, thereby automatically ensuring the uniqueness of the state data naming inside the Bean and avoiding data conflicts
- See: Bean Identifier
How to create a model bean
Zova provides a VSCode extension that allows you to easily create a model bean through the context menu
Context Menu - [Module Path]:
Zova Create/Bean: Model
Enter the name of model bean according to the prompt, such as todo
. The VSCode extension will automatically create the code skeleton of model bean
For example, create a Model Bean todo
in the demo-todo
module
demo-todo/src/bean/model.todo.ts
import { Model } from 'zova';
import { BeanModelBase } from 'zova-module-a-model';
@Model()
export class ModelTodo extends BeanModelBase {}
- Use
@Model
decorator - Inherited from base class
BeanModelBase
Async Data
The core of TanStack Query is to manage server-side data. For simplicity, only the definition and use of the select
method are shown here:
- For complete code examples, please see: demo-todo
How to define
@Model()
export class ModelTodo {
select() {
return this.$useQueryExisting({
queryKey: ['select'],
queryFn: async () => {
return this.scope.service.todo.select();
},
});
}
}
- Invoke
$useQueryExisting
to create a Query object- Why not use the
$useQuery
method? Because asynchronous data is generally loaded asynchronously when needed. Therefore, we need to ensure that the same Query object is always returned when theselect
method is invoked multiple times, so the$useQueryExisting
method must be used
- Why not use the
- Pass in
queryKey
to ensure the uniqueness of the local cache - Pass in
queryFn
and call this function at the appropriate time to obtain server data- service.todo.select: see Api service
How to use
demo-todo/src/page/todo/controller.ts
import { ModelTodo } from '../../bean/model.todo.js';
export class ControllerPageTodo {
@Use()
$$modelTodo: ModelTodo;
}
- Inject Model Bean instance:
$$modelTodo
demo-todo/src/page/todo/render.tsx
export class RenderTodo {
render() {
const todos = this.$$modelTodo.select();
return (
<div>
<div>isLoading: {todos.isLoading}</div>
<div>
{todos.data?.map(item => {
return <div>{item.title}</div>;
})}
</div>
</div>
);
}
}
- Invoke
select
method to obtain the Query object- The render method will be executed multiple times, and repeated calls to the
select
method return the same Query object
- The render method will be executed multiple times, and repeated calls to the
- Directly use the state and data of the Query object
How to support SSR
In SSR mode, we need to use asynchronous data like this: load the state data on the server, and then render it into an HTML string through the render method. The state data and HTML string will be sent to the client at the same time, and the client will still use the same state data when hydrating so as to maintain state consistency
To implement the above logic, only one step is required in Zova Model:
demo-todo/src/page/todo/controller.ts
import { ModelTodo } from '../../bean/model.todo.js';
export class ControllerPageTodo {
@Use()
$$modelTodo: ModelTodo;
protected async __init__() {
const queryTodos = this.$$modelTodo.select();
await queryTodos.suspense();
if (queryTodos.error) throw queryTodos.error;
}
}
- Just invoke
suspense
in the__init__
method to wait for asynchronous data loading to complete
Sync Data: localstorage
Since the server does not support window.localStorage
, the localstorage state data does not participate in the SSR hydration process
The following demonstrates storing user information in localstorage, and the state will be retained when the page is refreshed
How to define
export class ModelUser extends BeanModelBase {
user?: ServiceUserEntity;
protected async __init__() {
this.user = this.$useQueryLocal({
queryKey: ['user'],
});
}
}
- Unlike
async data
definition,sync data
is defined directly in the initialization method__init__
- Invoke
$useQueryLocal
to create a Query object - Pass in
queryKey
to ensure the uniqueness of the local cache
How to use
Read and set data directly like regular variables
const user = this.user;
this.user = newUser;
Sync Data: cookie
Cookies in Request Header
are automatically used on the server side, and document.cookie
is automatically used on the client side, thus automatically ensuring the consistency of cookie state data during SSR hydration
The following demonstrates storing the user Token in a cookie, and the state will be retained when the page is refreshed. Thus, in SSR mode, both the client and the server can use the same jwt token
to access the backend API services
How to define
export class ModelUser extends BeanModelBase {
token?: string;
protected async __init__() {
this.token = this.$useQueryCookie({
queryKey: ['token'],
});
}
}
- Unlike
async data
definition,sync data
is defined directly in the initialization method__init__
- Invoke
$useQueryCookie
to create a Query object - Pass in
queryKey
to ensure the uniqueness of the local cache
How to use
Read and set data directly like regular variables
const token = this.token;
this.token = newToken;
Sync Data: memory
In SSR mode, the global state data defined by the server will be synchronized to the client and automatically complete the hydration
The following demonstrates the memory-based global state data
How to define
zova-ui-quasar/src/suite-vendor/a-quasar/modules/quasar-adapter/src/bean/model.theme.ts
export class ModelTheme extends BeanModelBase {
cBrand: string;
protected async __init__() {
this.cBrand = this.$useQueryMem({
queryKey: ['cBrand'],
});
}
}
- Unlike
async data
definition,sync data
is defined directly in the initialization method__init__
- Invoke
$useQueryMem
to create a Query object - Pass in
queryKey
to ensure the uniqueness of the local cache
How to use
Read and set data directly like regular variables
const cBrand = this.cBrand;
this.cBrand = newValue;
Conclusion
Zova is a vue3 framework with ioc container. It combines the advantages of Vue/React/Angular in code style, while avoiding their shortcomings to make our development experience more elegant and reduce the mental burden. Zova has built-in a lot of interesting features, and the Model mechanism is just one of them.
Zova has been open sourced, welcome to follow and participate: https://github.com/cabloy/zova. You can contact me on twitter: https://twitter.com/zhennann2024
Top comments (0)