- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
在实际开发当中,会遇到四种全局状态数据:异步数据(一般来自服务端)、同步数据。同步数据又分为三种:localstorage、cookie、内存。在传统的 Vue3 当中,分别采用不同的机制来处理这些状态数据,而在 Zova 中只需要采用统一的Model机制 。
状态数据 | 传统的Vue3 | Zova |
---|---|---|
异步数据 | Pinia | Model |
localstorage | Pinia + Localstorage | Model |
cookie | Pinia + Cookie | Model |
内存 | Pinia | Model |
采用 Model 机制统一管理这些全局状态数据,就可以提供一些通用的系统能力,比如,内存优化、持久化和SSR支持等等,从而规范数据使用方式,简化代码结构,提升代码的可维护性 。
Zova Model 的基座是TanStack Query。TanStack Query 提供了强大的数据获取、缓存和更新能力。如果你没有使用过类似TanStack Query的数据管理机制,那么强烈建议了解一下,相信你一定会受到思想的洗礼 但是,TanStack Query 的核心是对异步数据(一般来自服务端)进行管理。Zova Model 在 TanStack Query 的基础上做了扩展,因此也支持同步数据的管理。换而言之,以下所述所有特性和能力同时适用于异步数据和同步数据 。
对获取的异步数据进行本地缓存,避免重复获取。对于同步数据,会自动针对 localstorage 或者 cookie 进行读写操作 。
提供数据过期策略,在合适的时机自动更新 。
在程序的多个地方同时访问数据,将只调用一次服务端 api。如果是同步数据,也只针对 localstorage 或者 cookie 调用一次操作 。
通过 Zova Model 管理的数据,虽然是全局范围的状态,但是并不总是占用内存,而是提供了内存释放与回收的机制。具体而言,就是在创建 Vue 组件实例时根据业务的需要创建缓存数据,当 Vue 组件实例卸载时释放对缓存数据的引用,到达约定的过期时间如果仍然没有其他 Vue 组件引用,就会触发回收机制(GC),完成对内存的释放,从而节约内存占用。这对于大型项目,用户需要长时间进行界面交互的场景,具有显著的好处 。
本地缓存可以持久化,当页面刷新时可以自动恢复,避免服务端调用。如果是异步数据,就会自动持久化到 IndexDB 中,从而满足大数据量的存储需要。如果是同步数据,就会自动持久化到 localstorage 或者 cookie 。
内存优化与持久化配合发挥作用,对于大型项目效果更佳明显。比如,第一次从服务端获取的数据,会生成本地缓存,并自动持久化。当页面不再使用并且过期时,会自动销毁本地缓存,从而释放内存。当再次访问该数据时,会自动从持久化中恢复本地缓存数据,而不是再次从服务端获取数据 。
不同类型的状态数据,在 SSR 模式下也会有不同的实现机制。Zova Model 把这些状态数据的差异进行抹平,并且采用统一的机制进行水合,从而让 SSR 的实现更加自然、直观,显著降低了心智负担 。
Zova 通过 Model Bean 来管理数据。而 Bean 本身有唯一的标识,可以作为数据的命名空间,从而自动保证了 Bean 内部状态数据命名的唯一性,避免数据冲突 。
Zova提供了VS Code插件,通过右键菜单可以非常便利的创建一个Model Bean 。
右键菜单 - [模块路径]: Zova Create/Bean: Model 。
依据提示输入 model bean 的名称,比如todo,VSCode 插件会自动添加 model bean 的代码骨架 。
比如,在 demo-todo 模块中创建一个 Model Bean todo 。
demo-todo/src/bean/model.todo.ts 。
import { Model } from 'zova';
import { BeanModelBase } from 'zova-module-a-model';
@Model()
export class ModelTodo extends BeanModelBase {}
TanStack Query 的核心是对服务端数据进行管理。为简化起见,这里仅展示select方法的定义与使用
@Model()
export class ModelTodo {
select() {
return this.$useQueryExisting({
queryKey: ['select'],
queryFn: async () => {
return this.scope.service.todo.select();
},
});
}
}
$useQuery
方法?因为异步数据一般是在需要时才进行异步加载。因此我们需要确保在多次调用select
方法时始终返回同一个 Query 对象,所以必须使用$useQueryExisting
方法demo-todo/src/page/todo/controller.ts 。
import { ModelTodo } from '../../bean/model.todo.js';
export class ControllerPageTodo {
@Use()
$$modelTodo: 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>
);
}
}
在 SSR 模式下,我们需要这样使用异步数据:在服务端加载状态数据,然后通过 render 方法渲染成 html 字符串。状态数据和 html 字符串会同时发送到客户端,客户端在进行水合时仍然使用此相同的状态数据,从而保持状态的一致性 。
要实现以上逻辑,在 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;
}
}
__init__
方法中调用suspense
等待异步数据加载完成由于服务端不支持window.localStorage,因此 localstorage 状态数据不参与 SSR 的水合过程 。
下面演示把用户信息存入 localstorage,当页面刷新时也会保持状态 。
export class ModelUser extends BeanModelBase {
user?: ServiceUserEntity;
protected async __init__() {
this.user = this.$useQueryLocal({
queryKey: ['user'],
});
}
}
异步数据
定义不同,同步数据直接在初始化方法__init__
中定义直接像常规变量一样读取和设置数据 。
const user = this.user;
this.user = newUser;
在服务端会自动使用Request Header中的 Cookies,在客户端会自动使用document.cookie,因此会自动保证 SSR 水合过程中 cookie 状态数据的一致性 。
下面演示把用户 Token 存入 cookie,当页面刷新时也会保持状态。这样,在 SSR 模式下,客户端和服务端都可以使用相同的jwt token访问后端 API 服务 。
export class ModelUser extends BeanModelBase {
token?: string;
protected async __init__() {
this.token = this.$useQueryCookie({
queryKey: ['token'],
});
}
}
异步数据
定义不同,同步数据直接在初始化方法__init__
中定义直接像常规变量一样读取和设置数据 。
const token = this.token;
this.token = newToken;
在 SSR 模式下,服务端定义的全局状态数据会同步到客户端,并自动完成水合 。
下面演示基于内存的全局状态数据 。
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'],
});
}
}
异步数据
定义不同,同步数据直接在初始化方法__init__
中定义直接像常规变量一样读取和设置数据 。
const cBrand = this.cBrand;
this.cBrand = newValue;
Zova 是一款支持 IOC 容器的 Vue3 框架,在代码风格上结合了Vue/React/Angular的优点,同时规避他们的缺点,让我们的开发体验更加优雅,减轻心智负担。Zova已经内置了大量实用、有趣的功能特性,Model机制仅仅是其中一个 。
Zova框架已经开源,欢迎关注,参与共建:https://github.com/cabloy/zova。可添加我的微信,入群交流:yangjian2025 。
最后此篇关于在Vue3中如何实现四种全局状态数据的统一管理?的文章就讲到这里了,如果你想了解更多关于在Vue3中如何实现四种全局状态数据的统一管理?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在通读 Windows Phone 7.5 Unleashed,有很多代码看起来像这样(在页面的代码隐藏中): bool loaded; protected override void OnNav
在cgi服务器中,我这样返回 print ('Status: 201 Created') print ('Content-Type: text/html') print ('Location: htt
我正在查看 esh(easy shell)的实现,无法理解在这种情况下什么是 22 和 9 信号。理想情况下,有一个更具描述性的常量,但我找不到列表。 最佳答案 信号列表及其编号(包括您看到的这两个)
我的Oozie Hive Action 永远处于运行模式。 oozie.log文件中没有显示错误。
我正在编写一个使用 RFCOMM 通过蓝牙连接到设备的 Android 应用程序。我使用 BluetoothChat 示例作为建立连接的基础,大部分时间一切正常。 但是,有时由于出现套接字已打开的消息
我有一个云调度程序作业,它应该每小时访问我的 API 以更新一些价格。这些作业大约需要 80 秒才能运行。 这是它的作用: POST https://www.example.com/api/jobs/
我正在 Tomcat 上访问一个简单的 JSP 页面: 但是当我使用 curl 测试此页面时,我得到了 200 响应代码而不是预期的 202: $ curl -i "http://localhos
有时 JAR-RS 客户端会发送错误的语法请求正文。服务器应响应 HTTP status 400 (Bad Request) , 但它以 HTTP status 500 (Internal Serve
我正在尝试通过 response.send() 发送一个整数,但我不断收到此错误 express deprecated res.send(status): Use res.sendStatus(sta
我已经用 Excel 和 Java 做过很多次了……这次我需要用 Stata 来做,因为保存变量更方便'labels .如何将 dataset_1 重组为下面的 dataset_2? 我需要转换以下
我正在创建一个应用程序,其中的对象具有状态查找功能。为了提供一些上下文,让我们使用以下示例。 帮助台应用程序,其中创建作业并通过以下工作流程移动: 新 - 工作已创建但未分配 进行中 - 分配给工作人
我想在 Keras 中运行 LSTM 并获得输出和状态。在 TF 中有这样的事情 with tf.variable_scope("RNN"): for time_step in range
有谁知道 Scala-GWT 的当前状态 项目? 那里的主要作者 Grzegorz Kossakowski 似乎退出了这个项目,在 Spring 中从事 scalac 的工作。 但是,在 interv
我正在尝试编写一个 super 简单的 applescript 来启动 OneDrive App , 或确保打开,当机器的电源设置为插入时,将退出,或确保关闭,当电源设置为电池时。 我无法找到如何访问
目前我正在做这样的事情 link.on('click', function () { if (link.attr('href') !== $route.current.originalPath
是否可以仅通过查看用户代理来检测浏览器上是否启用/禁用 Javascript。 如果是,我应该寻找什么。如果否,检测用户浏览器是否启用/禁用 JavaScript 的最佳方法是什么 最佳答案 不,没有
Spring 和 OSGi 目前的开发状况如何? 最近好像有点安静了。 文档的最新版本 ( http://docs.spring.io/osgi/ ) 来自 2009 年。 我看到一些声明 Sprin
我正在从主函数为此类创建一个线程,但即使使用 Thread.currentThread().interrupt() 中断它,输出仍然包含“Still Here”行。 public class Writ
为了满足并发要求,我想知道如何在 Godog 中的多个步骤之间传递参数或状态。 func FeatureContext(s *godog.Suite) { // This step is ca
我有一个UIButton子类,它不使用UIImage背景,仅使用背景色。我注意到的一件事是,当您设置按钮的背景图像时,有一个默认的突出显示状态,当按下按钮时,该按钮会稍微变暗。 这是我当前的代码。
我是一名优秀的程序员,十分优秀!