基于Vue3做一套适合自己的状态管理(五)组合:setup 风格,更灵活

1,020 阅读2分钟

计划章节

  1. 基类:实现辅助功能
  2. 继承:充血实体类
  3. 继承:OptionApi 风格的状态
  4. Model:正确的打开方式
  5. 组合:setup 风格,更灵活
  6. 注册状态的方法、以及局部状态和全局状态
  7. 实践:当前登录用户的状态
  8. 实践:列表页面需要的状态

使用setup风格做状态,更灵活

上两章说的是使用继承的方式实现状态,这次我们换成组合的方式,体验一下极致的灵活。

组合,关键看思路

我们先看看可以用了组合的元素:

  • 普通对象
  • 基类
  • ref
  • computed
  • reactive
  • readonly
  • watch
  • 函数
  • 其他

做一个 List 的语法糖

上一次我们做了一个Model的语法糖,这次我们做一个List的:

/**
 * 给 BaseArray 套个壳,加上 reactive 实现响应性 & IState
 * @param val 数组或者函数
 * @returns 
 */
export default function List<T>(val: IArrayOrFunction): Array<T> & IState {
  const re = new baseArray(val)
  return reactive(re)
}

组合一下

我们做一个简单的数据列表的状态:

const useState = () => {

    const name = ref('我是一个字符串')

    // 可以直接赋值的数组
    const dataList2 = List([])

    // 原生数组
    const dataList = reactive([{
      name: '我是 setup',
      age: 10
    }])

    // 分页信息
    const pageInfo = reactive({
      index: 1,
      count: 30
    })

    const load = () => {
      const index = pageInfo.index
      // 加载数据
      dataList2.$state = [{
        name: '我是 setup',
        age: 10 + index
      }]
    }

    watch(() => pageInfo.index, () => {
      // 根据分页信息获取数据
      load()
    })

    return {
      name,
      dataList,
      dataList2,
      dataList3: readonly(dataList2),
      pageInfo,
      load
    }

  }

直接组合起来,并没有转化为 state、getter、action 的结构,这样虽然有点乱,但是也有优点:

  • 灵活
    • 如果不需要直接赋值,可以使用原生的对象、数组;
    • 如果需要直接赋值,可以使用基类(Model、List);
    • 如果需要只读,可以使用readonly;
    • 还可以使用 watch、computed 等;
    • 可以轻松和其他状态联动;
    • 总之,需要什么就加入什么,非常灵活。
  • 用 watch 联动各个状态
    可以分别设置一个或者多个状态,然后可以用 watch 把各个状态联动起来,没有“割裂”感

结构

450setup结构.jpg

似乎好像有点乱,不过好用就好。

没有固定的state、action这样的格式,完全看如何组合。虽然看起来很乱,其实这和 compositionAPI 的 setup 才是一样的风格,也就是传说中的心智负担。

关于 Pinia 的 setup 方式

观察了 Pinia 的 setup 方式创建的状态,其结构和Option方式的一致,不是太理解这样做的目的,难道是为了统一结构吗?想想也是,使用状态的时候,不需要关心是采用哪种方式似乎也挺好。

想想也是,如果使用状态的时候,还需要先了解一下结构(创建方式),是不是会增加心智负担?

不过,如果优点大于缺陷的话,我觉得还是可以尝试一下的。

源码

gitee.com/naturefw-co…

在线演示

naturefw-code.gitee.io/nf-rollup-s…