1.0.29 • Published 2 years ago

binia v1.0.29

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

inspired by valtio

Demo

install

npm i binia

Api

defineStore

定义 store, computed 属性也支持 setter, 注意由于使用 this 访问属性, 所以不能使用箭头函数

import { defineStore } from "binia";
const store = defineStore({
  state: { count: 1 },
  computed: {
    doubled() {
      return this.count * 2;
    },
    quadrupled: {
      get() {
        return this.doubled * 2;
      },
      set(v: number) {
        this.count = v >> 2;
      },
    },
  },
});

const state2 = defineStore({
  state: {
    firstName: "Alec",
    lastName: "Baldwin",
  },
  computed: {
    fullName: {
      get() {
        return this.firstName + " " + this.lastName;
      },
      set(newValue: string) {
        [this.firstName, this.lastName] = newValue.split(" ");
      },
    },
  },
});

options

computedCacheSize: 自定义computed的缓存大小, 默认2 demo

useSnapshot

在组件中使用 store 中的数据, useSnapshot 返回只读对象, 通过拦截 getter 收集组件中具体使用了那些属性, 只有被用到的属性发生变化后才会更新组件, 不需要使用 Context 或者 Provider 等 api

function C() {
  const { count, doubled, quadrupled } = useSnapshot(store);
  return (
    <div>
      <h2>count:{count}</h2>
      <h2>doubled:{doubled}</h2>
      <h2>quadrupled:{quadrupled}</h2>
    </div>
  );
}

action

action 就是一个简单的修改 store 的普通函数

const inc = () => store.count++;

const decAsync = async (v = 1) => {
  await sleep(1000);
  store.count -= v;
};

derive

用 derive 函数定义一个派生自多个 store 的新 store, 每个属性都是一个参数为 get 的函数, 访问时的属性值为函数返回值, 通过 get 函数收集依赖, 下面的案例中 storeC.c 变化后属性 ab 是不会变化的, 只有 storeA.a 或者 storeB.b 变化后 ab 才会更新, 对应的组件也会重新 render

const storeA = defineStore({ state: { a: 1 } });
const storeB = defineStore({ state: { b: 1 } });
const storeC = defineStore({ state: { c: 1 } });

const storeD = derive({
  ab(get) {
    return get(storeA).a + '--' + get(storeB).b + '--' + storeC.c;
  },
});

connect

可以在class组件中使用

const inc = () => {
  store.count++;
};
type Store = typeof store;
type Snap = Snapshot<Store>;
const mapState = (snap: Snap) => {
  return {
    c: snap.count,
    d: snap.quadrupled,
  };
};
type MapState = ReturnType<typeof mapState>;
type MapActions = ReturnType<typeof mapActions>;
type Props = { name: string };

const mapActions = (store: Store) => {
  return {
    inc,
    dec: () => {
      store.count--;
    },
  };
};

class A extends React.Component<MapActions & MapState & Props> {
  render() {
    return (
      <div>
        <h2>c:{this.props.c}</h2>
        <h2>d:{this.props.d}</h2>
        <button onClick={this.props.inc}>inc</button>
        <button onClick={this.props.dec}>dec</button>
      </div>
    );
  }
}

const C = connect(store, mapState, mapActions)(A);

devtools

安装Redux DevTools 插件, 然后调用devtools函数开启

import { devtools, defineStore } from 'binia';

const store = defineStore({
  state: { count: 1 },
  computed: {
    doubled() {
      return this.count * 2;
    },
    quadrupled: {
      get() {
        return this.doubled * 2;
      },
      set(v: number) {
        this.count = v >> 2;
      },
    },
  },
});
devtools(store, { name: 'demo',enabled: true })

TS 支持

自定义类型

有些时候自动类型推导会无法推导 union 等类型, 需要手动标注类型

const state: { mode: "dev" | "prod" } = { mode: "dev" };
const store = defineStore({ state });

// 或者使用as
const store = defineStore({ state: { mode: "dev" as "dev" | "prod" } });

在 derive 中访问 computed

由于 ts 的限制, 目前并不能在 derive 函数中访问自己的 computed 属性, 功能上支持, 只是类型推导上无法支持, 可以使用 as 规避, 或者使用 derive 函数创建新 store

const storeA = defineStore({
  state: { h: "hello", w: "world" },
  computed: {
    hw() {
      return this.h + " " + this.w;
    },
  },
});
const storeB = defineStore({
  state: { count: 1 },
  computed: {
    doubled() {
      return this.count * 2;
    },
  },
  derive: {
    helloCount(get) {
      return "hello: " + get(this).count + get(storeA).hw;
    },
    helloDouble(get) {
        // 使用as语法规避
      return 'hello: ' + get(this as unknown as { doubled: number }).doubled + get(storeA).hw
    },
  },
});


const storeC = derive({
  helloCount(get) {
    return 'hello: ' + get(store).count + get(storeA).hw;
  },
  helloDouble(get) {
    return 'hello: ' + get(store).doubled + get(storeA).hw;
  },
})
1.0.26

2 years ago

1.0.25

2 years ago

1.0.29

2 years ago

1.0.28

2 years ago

1.0.27

2 years ago

1.0.19

2 years ago

1.0.18

2 years ago

1.0.22

2 years ago

1.0.21

2 years ago

1.0.20

2 years ago

1.0.24

2 years ago

1.0.23

2 years ago

1.0.17

2 years ago

1.0.16

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.11

2 years ago

1.0.10

2 years ago

1.0.15

2 years ago

1.0.14

2 years ago

1.0.13

2 years ago

1.0.12

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago