4.0.2 • Published 8 months ago

@helux/store-pinia v4.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

helux-store-pinia

一个优雅的类似 pinia 开发体验的 react 状态管理库,基于 helux 开发

安装

npm i @helux/store-pinia

简单例子

const storeCtx = defineStore('Counter', {
  // 定义状态(必须)
  state: () => ({ count: 0 }),
  // 定义带缓存的派生属性(可选)
  getters: {
    countDouble() {
      return this.count * 2;
    },
  },
  // 定义方法修改状态(可选)
  actions: {
    // 同步方法
    addCount(payload: number) {
      this.count = payload;
    },
    // 异步方法
    async addCountAsync(paload: number) {
      await delay();
      this.count = payload;
      // or
      // this.addCount(payload);
    },
  },
});

复杂例子

创建 store

const storeCtx = defineStore('BookStore', {
  // 定义状态(必须)
  state: () => ({ list: [] as IBook[], page: 1, size: 10, total: 8, mountCount: 0 }),
  // 定义带缓存的派生属性(可选)
  getters: {
    // 由 state 派生出 totalPlus,上游依赖不变化时此函数不再重复计算
    totalPlus() {
      return this.total + 1;
    },
    // 由其他 getters 派生出 totalPlus2,上游依赖不变化时此函数不再重复计算
    totalPlus2() {
      return this.totalPlus + 100;
    },
  },
  // 定义方法修改状态(可选)
  actions: {
    // 同步方法
    changeTotal(payload: number) {
      this.total = payload;
    },
    // 异步方法
    async fetchList(payload: { page: number; size: number }, p2: number) {
      console.log(payload.page, payload.size);
      await delay();
      const { list, total } = await Promise.resolve({
        list: [
          { id: '1', name: `state_${Date.now()}`, price: 100 },
          { id: '2', name: `helex_${Date.now()}`, price: 100 },
        ],
        total: 10,
      });
      this.list = list;
      this.total = total;
    },
  },
  // 定义生命周期(可选),包含 willMount mounted willUnmount, 含义见 ILifeCycle 定义,
  // lifecycle 方法可访问 actions 里的方法,也可以访问 state 并修改,
  // 但是在 actions 里是访问不到 lifecycle 的,只能由框架负责调用,
  lifecycle: {
    mounted() {
      this.mountCount += 1;
    },
  },
});

组件里使用

function Shop() {
  const store = storeCtx.useStore();
  const ld = storeCtx.useLoading();
  // fetchList 的运行状态,如关系其他函数运行状态,可从 ld 继续解构获取到
  const { loading, err, ok } = ld.fetchList;

  return (
    <div>
      {loading && <h1>fetching books</h1>}
      {err && <h1>{err.message}</h1>}
      {ok
        && store.list.map((v) => (
          <div key={v.id}>
            name:{v.name} price:{v.price}
          </div>
        ))}
      <h3>total {store.total}</h3>
      <h3>totalPlus {store.totalPlus}</h3>
      <button onClick={() => store.fetchList({ page: 1, size: 10 }, 222)}>more</button>
      <button onClick={() => store.changeTotal(Date.now())}>change total</button>
      <button onClick={() => storeCtx.reset()}>reset</button>
    </div>
  );
}

信号感知

// 细粒度绑定
function Other() {
  return (
    <div>
      total: {$(storeCtx.state.totalPlus)}
      <br />
      totalPlus2: {$(storeCtx.state.totalPlus2)}
      <br />
      mountCount: {$(storeCtx.state.mountCount)}
    </div>
  );
}

打印快照

function Snap() {
  storeCtx.useStore();
  return (
    <div style={{ border: '3px solid red', padding: '10px', margin: '12px' }}>
      Snap: {JSON.stringify(storeCtx.getSnap())}
      <br />
      GettersSnap: {JSON.stringify(storeCtx.getGettersSnap())}
      <button
        onClick={() => {
          console.log(storeCtx);
        }}
      >
        see store context
      </button>
    </div>
  );
}

添加 redux devtool 插件

import { HeluxPluginDevtool } from '@helux/plugin-devtool';

import { addPlugin } from '@helux/store-pinia';
addPlugin(HeluxPluginDevtool);

下图即添加开发差距后的效果

Image

对应代码如下

import { defineStore } from '@helux/store-pinia';

interface IBook {
  id: string;
  name: string;
  price: number;
}

const delay = (ms = 1000) => new Promise((r) => setTimeout(r, ms));
export const storeCtx = defineStore('DefineStoreDemo', {
  state: () => ({
    list: [] as IBook[],
    page: 1,
    size: 10,
    total: 221,
    mountCount: 0,
    time: 0,
    a: 1,
    b: 2,
    c: 3,
    d: 4,
  }),
  getters: {
    // 由 state 派生出 totalPlus,上游依赖不变化时此函数不再重复计算
    totalPlus() {
      return this.total + 1;
    },
    // 由其他 getters 派生出 totalPlus2,上游依赖不变化时此函数不再重复计算
    totalPlus2() {
      return this.totalPlus + 100;
    },
  },
  actions: {
    // 同步方法
    changeTotal(payload: number) {
      this.total = payload;
    },
    async otherFn(test?: number, test2?: number) {
      await delay(); // ❌ <--- 此处之前无变更,故不会提交
      this.a = Date.now();
      await delay(); // ✅ <--- 在此之前有数据变更,触发提交
      this.b = Date.now();
      await delay(); // ✅<--- 在此之前有数据变更,触发提交
      this.c = Date.now();
      // ✅<--- 结束 action,在此之前有数据变更,触发提交
    },
    // 异步方法
    async fetchList(payload: { page: number; size: number }, p2: number) {
      console.log('START fetchList', payload.page, payload.size);
      await delay(); // ❌ <--- 此处之前无变更,故不会提交
      this.a = Date.now();
      await delay(); // <--- ✅ 在此之前有数据变更,触发提交
      this.b = Date.now();
      await delay(); // <--- ✅ 在此之前有数据变更,触发提交
      this.c = Date.now();
      await delay(); // <--- ✅ 在此之前有数据变更,触发提交
      await this.otherFn(111, 222);
      const { list, total } = await Promise.resolve({
        list: [
          { id: '1', name: `state_${Date.now()}`, price: 100 },
          { id: '2', name: `helex_${Date.now()}`, price: 100 },
        ],
        total: 10,
      });
      this.list = list;
      this.total = total;
      console.log('End fetchList', payload.page, payload.size);
      // ✅<--- 结束 action,在此之前有数据变更,触发提交
    },
  },
});

添加自定义插件( 接收来自 helux 内部的各种事件并做对应处理 )

import { addPlugin, IPlugin } from '@helux/store-pinia';

const MyPlugin: IPlugin = {
  install(pluginCtx) {
    pluginCtx.on('ON_SHARE_CREATED', (dataInfo) => {
      // do some staff here
      // console.log('ON_SHARE_CREATED', dataInfo);
    });
    pluginCtx.on('ON_DATA_CHANGED', (dataInfo) => {
      // console.log('ON_DATA_CHANGED', dataInfo);
    });
  },
  name: 'MyPlugin',
};

addPlugin(MyPlugin);

添加自定义中间件(中间件在变更提交之前按添加顺序依次执行)

import { addMiddleware, Middleware } from '@helux/store-pinia';

const myMiddleware: Middleware = (mid) => {
  if (mid.moduleName) {
    // 来自某个模块,修改一下时间戳
    mid.draft.timestamp = new Date();
  }
};

addMiddleware(myMiddleware);
4.0.2

8 months ago

4.0.1

8 months ago

4.0.0

8 months ago

3.0.1

8 months ago

3.0.0

8 months ago

2.0.1

9 months ago

2.0.0

9 months ago

1.1.0

9 months ago

1.0.10

10 months ago

1.0.9

10 months ago

1.0.8

10 months ago

1.0.7

10 months ago

1.0.6

10 months ago

1.0.5

10 months ago

1.0.4

10 months ago

1.0.2

10 months ago

1.0.1

10 months ago

1.0.0

10 months ago