阅读视图

发现新文章,点击刷新页面。

easy-model:简化领域驱动开发的理想选择

在现代前端开发中,领域驱动设计(DDD)正成为越来越多项目的首选。easy-model 框架以其独特的模型驱动架构,为开发者提供了便捷的 DDD 实现途径。本文将重点介绍 easy-model 如何助力领域驱动开发、提升可测试性,并保持简单易用。

领域驱动开发的便捷实现

easy-model 的核心在于模型类封装。每个模型类代表一个业务领域,内部封装状态和逻辑,避免了传统状态管理的分散。这种设计让业务逻辑集中,易于理解和维护,完美契合 DDD 的理念。

import { useModel } from "easy-model";

class UserDomain {
  user = { id: "", name: "", email: "" };
  constructor(initialUser = { id: "", name: "", email: "" }) {
    this.user = initialUser;
  }

  updateUser(newUser: typeof this.user) {
    this.user = { ...this.user, ...newUser };
  }

  validateEmail() {
    return this.user.email.includes("@");
  }
}

function UserComponent() {
  const userDomain = useModel(UserDomain, [{ id: "1", name: "张三", email: "zhangsan@example.com" }]);

  return (
    <div>
      <h2>{userDomain.user.name}</h2>
      <p>邮箱有效: {userDomain.validateEmail() ? "是" : "否"}</p>
      <button onClick={() => userDomain.updateUser({ name: "李四" })}>
        更新姓名
      </button>
    </div>
  );
}

通过 useModel,组件直接创建并订阅模型实例。模型类的方法封装业务逻辑,如验证和更新,确保领域知识内聚。相比 Redux 的 action/reducer 分离,easy-model 更贴近 OOP 思维。

卓越的可测试性

模型类作为纯逻辑单元,便于单元测试,无需复杂 mocking。

import { describe, it, expect } from "vitest";
import { provide } from "@e7w/easy-model";

describe("UserDomain", () => {
  it("should validate email correctly", () => {
    const model = provide(UserDomain)({
      id: "1",
      name: "Test",
      email: "test@example.com",
    });
    expect(model.validateEmail()).toBe(true);

    model.updateUser({ email: "invalid" });
    expect(model.validateEmail()).toBe(false);
  });

  it("should update user", () => {
    const model = provide(UserDomain)({
      id: "1",
      name: "Old",
      email: "old@example.com",
    });
    model.updateUser({ name: "New" });
    expect(model.user.name).toBe("New");
  });
});

框架的实例缓存机制(provide)允许按参数分组,确保测试隔离。依赖注入通过 inject 装饰器和容器配置,支持 mock 替换,提升集成测试效率。

简单易用的开发体验

easy-model 摒弃复杂配置,安装即用。严格 TypeScript 模式确保类型安全,无需担心运行时错误。API 设计简洁,仅需几个钩子即可上手。

React 集成无缝:

import { useModel, useWatcher } from "easy-model";

function CounterComponent() {
  const counter = useModel(CounterModel, [0, "计数器"]);

  useWatcher(counter, (keys, prev, next) => {
    console.log(`字段 ${keys.join(".")}${prev} 变为 ${next}`);
  });

  return (
    <div>
      <h2>{counter.label}</h2>
      <div>{counter.count}</div>
      <button onClick={() => counter.decrement()}>-</button>
      <button onClick={() => counter.increment()}>+</button>
    </div>
  );
}

异步操作使用 @loader.load 装饰器,useLoader 钩子查询状态,简化加载处理。@offWatch 优化性能,避免不必要的监听。跨组件共享通过 provideuseInstance 实现。

性能与扩展性

easy-model 使用 Proxy 实现深层变更监听,支持嵌套对象和引用关系变化。watch 函数允许非 React 环境监听,useWatcher 处理组件副作用。IoC 容器支持 namespace 隔离,便于大型应用管理。

相比 Redux/MobX,easy-model 减少 boilerplate,提升开发效率。Benchmark 示例显示其在性能上具备竞争力。

总结

easy-model 以模型为中心,完美支持领域驱动开发。其类封装设计提升可测试性,简洁 API 保证易用性。无论是小型项目还是复杂应用,都能显著提升开发效率。

立即试用 easy-model,体验更优雅的前端开发!项目地址:GitHub

easy-model 实战:跨组件通信、监听与异步加载,一库搞定 React 状态难题

在 React 开发中,状态管理往往是痛点:Redux 太重,Zustand 太轻,MobX 学习成本高。今天分享一个平衡的选择:easy-model,一个基于类模型的工具集。它不仅简化了状态管理,还内置 IoC 和监听能力。让我通过几个实战场景带大家看看它的威力。

场景1:跨组件通信(实例共享)

import { useModel } from "easy-model";

class CommunicateModel {
  constructor(public name: string) {}
  value = 0;
  random() {
    this.value = Math.random();
  }
}

function CommunicateA() {
  const { value, random } = useModel(CommunicateModel, ["channel"]);
  return (
    <div>
      <span>组件 A:{value}</span>
      <button onClick={random}>改变数值</button>
    </div>
  );
}

function CommunicateB() {
  const { value } = useModel(CommunicateProvider, ["channel"]);
  return <div>组件 B:{value}</div>;
}

组件 A 改变数值,组件 B 立刻更新。天然支持「按业务 key 分区」状态。

场景2:精细化监听(watch 与 offWatch)

监听模型变化,跳过某些字段以优化性能:

import { watch, offWatch } from "easy-model";

class WatchModel {
  constructor(public name: string) {}
  value = 0;
  @offWatch
  internalCounter = 0; // 跳过监听,提高性能

  increment() {
    this.value += 1;
    this.internalCounter += 1;
  }
}

const inst = provide(WatchModel)("demo");
const stop = watch(inst, (keys, prev, next) => {
  console.log(`${keys.join(".")}: ${prev} -> ${next}`);
});

inst.increment(); // 只输出 value 的变更
stop();

适合日志记录、外部同步等场景。

场景3:异步加载管理(loader 与 useLoader)

统一处理 loading 状态:

import { loader, useLoader, useModel } from "easy-model";

class LoaderModel {
  constructor(public name: string) {}

  @loader.load(true)
  async fetch() {
    return new Promise<number>(resolve =>
      setTimeout(() => resolve(42), 1000)
    );
  }
}

function LoaderDemo() {
  const { isGlobalLoading, isLoading } = useLoader();
  const inst = useModel(LoaderModel, ["demo"]);

  return (
    <div>
      <div>全局加载:{String(isGlobalLoading)}</div>
      <div>当前方法加载:{String(isLoading(inst.fetch))}</div>
      <button onClick={() => inst.fetch()} disabled={isGlobalLoading}>
        加载数据
      </button>
    </div>
  );
}

适用场景

  • 领域模型清晰的项目(用类承载业务)。
  • 需要依赖注入的中大型应用(内置 IoC)。
  • 对性能敏感的批量更新场景(benchmark 显示个位数毫秒)。

easy-model 让我在项目中少写了很多模板代码,心智负担低。感兴趣的同学可以去 GitHub 看看示例:github.com/ZYF93/easy-…

npm 安装:npm install @e7w/easy-model

你用过哪些状态管理方案?觉得 easy-model 怎么样?评论区聊聊!

❌