为什么我使用 Umi 的 model 简易数据流管理插件

简介: Umi 是一款企业级的 React 前端应用框架,云巧产业数字组件中心推荐使用基于 Umi 的 Koi 框架统一前端应用研发流程,支撑前端项目从研发、联调到上线、发布的全流程。本文假设您正在或计划使用 Umi 或 Koi 作为底层框架支撑前端应用的开发,并且对 Umi 有一定的了解。## 数据治理的原则React 的核心特征是“数据驱动视图”,用公式表达即 `UI = render(d

Umi 是一款企业级的 React 前端应用框架,云巧产业数字组件中心推荐使用基于 Umi 的 Koi 框架统一前端应用研发流程,支撑前端项目从研发、联调到上线、发布的全流程。

本文假设您正在或计划使用 Umi 或 Koi 作为底层框架支撑前端应用的开发,并且对 Umi 有一定的了解。

数据治理的原则

React 的核心特征是“数据驱动视图”,用公式表达即 UI = render(data),通过数据变化来驱动视图变化。React 将组件内部自有的数据称作 state(状态),通过管理 state 来实现对组件的管理。

通过 Props 传参,可以在 React 中实现简单的父子、子父和兄弟组件间数据传递。对于跨级组件间的数据传递,React 提供了基于生产者-消费者模式的 Context API 来实现全局通信。

随着应用的膨胀,组件内部的状态变得愈加复杂,数据流管理的成本也越来越高。如果说所有代码的末路都是成为一座难以维护的大山的话,在那之前,我们应当好好想想如何尽可能多地延长代码的寿命,去重新思考我们的 React 项目的代码组织逻辑。

Umi 建议将所有组件降级为“无状态组件”,仅仅依赖 Props 或 Context 进行渲染。这样,在 UI 层面仅关心用户交互和渲染的逻辑,在单独的数据层去关心数据处理的逻辑。以 Umi 项目为例,具体而言就是:

  • src/models 中的文件管理数据层的逻辑,包含网络请求、数据处理等。
  • src/pages 中的页面组件与数据层进行交互,并将得到的数据通过 Props 或 Context 传递给通用组件,进行页面渲染。
  • src/components 中的通用组件仅仅依赖从 Props 或 Context 得到的数据进行渲染,不与数据层发生直接交互。

介绍 model 简易数据流插件

Umi 的 model 简易数据流插件就是基于 Context 的封装,使得数据能够在项目全局共享与使用。相比原生的 Context API,model 简易数据流插件更加便于使用。

使用 Context API 时,需要创建上下文对象,并在渲染树顶层包装上下文的 Provider:

// src/contexts/userContext.tsx
import React, { createContext, useState } from "react";
export const UserContext = createContext();
export const UserContextProvider = (props) => {
  const [username, setUsername] = useState<string>("");
  return (
    <UserContext.Provider value={{ username }}>
      {props.children}
    </UserContext.Provider>
  );
};

// src/layouts/index.tsx
import React from "react";
import { Outlet } from "umi";
import { UserContextProvider } from "@/contexts/userContext";
export const Layout = () => {
  return (
    <UserContextProvider>
      <Outlet />
    </UserContextProvider>
  );
};
export default Layout;

使用简易数据流插件可以略去创建上下文对象和包装 Provider 的过程,仅需要按约定目录导出一个自定义的 hook 函数即可:

// src/models/userModel.ts
import { useState } from "react";
export default function () {
  const [username, setUsername] = useState<string>("");
  return { username };
}

在组件使用上下文中存储的数据时,Context API 需要:

import React, { useContext } from "react";
import { UserContext } from "@/contexts/userContext";
export const pageElement = () => {
  const { username } = useContext(UserContext);
  return <>{username}</>;
};
export default pageElement;

而使用简易数据流插件可以略去引入指定上下文对象的过程,Umi 已经自动为它创建了一个命名空间:

import React from "react";
import { useModel } from "umi";
export const pageElement = () => {
  const { username } = useModel("userModel");
  return <>{username}</>;
};
export default pageElement;

由于调用了 useContext 的组件总会在 context 值变化时重新渲染,可能需要使用 useMemomemo 来优化重渲染开销较大的组件:

import React, { useContext, useMemo } from "react";
import { UserContext } from "@/contexts/userContext";
export const pageElement = () => {
  const { username } = useContext(UserContext);
  return useMemo(() => {
    return <ExpensiveTree username={username} />;
  }, [username]);
};
export default pageElement;

使用简易数据流插件时同样可以使用 useMemomemo 来进行优化,但更好的选择是直接利用 useModel() 提供的过滤方法,只关心需要的数据:

import React from "react";
import { useModel } from "umi";
export const pageElement = () => {
  const { username } = useModel("userModel", (model) => ({
    username: model.username,
  }));
  return <ExpensiveTree username={username} />;
};
export default pageElement;

综上所述,Umi 的 model 简易数据流插件实现了对 Context API 的较好封装,能够降本增效,简化代码的编写。对于需要使用 Context 管理数据流的情况,都可以使用 model 简易数据流插件替代。

什么时候使用 model 简易数据流插件

近年来,微前端架构的兴起为企业前端应用开发注入了新的活力,随着巨型前端应用拆解成一个个小微型前端应用,页面数据的治理难度也大大降低了。

当您使用 Umi 或 Koi 开发小微型前端应用遇到全局状态共享或数据流管理需求时,model 简易数据流插件具有便利低心智负担的优势,不妨好好利用它来管理页面数据。

针对更复杂的数据流管理需求(例如数据可预知甚至可回溯等),model 简易数据流插件显得有些捉襟见肘了:它只负责将数据全局化。别担心,开源社区提供了大量专注于做好数据流管理这件事的方案,例如 ReduxMobX 等;Umi 官方目前也提供了对接 dvaValtio 数据流管理库的插件,开箱即用。

相关文章
|
存储 缓存 文件存储
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
32699 79
如何保证分布式文件系统的数据一致性
|
前端开发 容器
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局(上)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局
17754 20
|
设计模式 存储 监控
设计模式(C++版)
看懂UML类图和时序图30分钟学会UML类图设计原则单一职责原则定义:单一职责原则,所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。bad case:IPhone类承担了协议管理(Dial、HangUp)、数据传送(Chat)。good case:里式替换原则定义:里氏代换原则(Liskov 
36685 19
设计模式(C++版)
|
存储 编译器 C语言
抽丝剥茧C语言(初阶 下)(下)
抽丝剥茧C语言(初阶 下)
|
机器学习/深度学习 人工智能 自然语言处理
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
24760 14
|
机器学习/深度学习 弹性计算 监控
重生之---我测阿里云U1实例(通用算力型)
阿里云产品全线降价的一力作,2023年4月阿里云推出新款通用算力型ECS云服务器Universal实例,该款服务器的真实表现如何?让我先测为敬!
36663 15
重生之---我测阿里云U1实例(通用算力型)
|
SQL 存储 弹性计算
Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
|
存储 算法 Java
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务
随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。
29838 52

热门文章

最新文章

下一篇
开通oss服务