qn-fe-core

1.0.1 • Public • Published

Qiniu fe-core

前端基础库,定位是框架/界面库无关的基础工具,内容围绕状态管理方案实现,包括:

  • Disposable 类实现及基于 mobx 的 Store 类实现
  • 副作用(fetch / router / storage)与 Store 的绑定实现

fe-core 采用 Typescript 实现,对使用方没有要求,ES 项目中也可以引入 fe-core 并使用。

为什么

响应式编程(Reactive Programing)的好处

响应式编程的范式,适合实现状态随用户交互、时间变更的复杂应用逻辑。将应用的行为拆解为正交的两个部分:数据的维护逻辑与数据推导出的逻辑,便于逻辑的组织与实现。

例如,在 name 每次改变时打印出 name 的值:(这里以 MobX 提供的能力为例)

// 第一种方式,每次修改完手动调用 `console.log`,缺点:很难避免遗漏
o.name = 'foo'
console.log(o.name)
 
// 第二种方式,提供专门的用于修改 `name` 的方法,缺点:
// 要么不一致(有的值通过 `=` 有的值通过 `set` 方法)
// 要么繁琐(所有的值都要通过特定的 `set` 方法修改)
const o = {
    setName(name) {
        this.name = name
        console.log(name)
    }
}
o.name = 'foo'
 
// 基于响应式的数据,手动指定观测对象(依赖)
reaction(
    () => o.name,
    name => console.log(name)
)
 
// 基于响应式的数据,自动收集观测对象(依赖)
autorun(
    () => console.log(o.name)
)

再如,根据 firstNamelastName 计算得到 fullName

// 第一种方式,每次修改完 `firstName` 或 `lastName` 都记得重新计算 `fullName` 并赋值
// 缺点:繁琐且很难避免遗漏,有多少处对数据的修改,就需要维护多少处逻辑
o.firstName = 'foo'
o.lastName = 'bar'
o.fullName = getFullName(o.firstName, o.lastName)
 
// 第二种方式,提供专门的用于修改 `fistName` & `lastName` 的方法
// 缺点:有多少计算依赖,就需要实现多少处的 set 方法,需要维护 m * n 处逻辑
// (m 为 `fullName` 这样的复杂逻辑的数量,n 为逻辑依赖的数据项数)
const o = {
    setFirstName(firstName) {
        this.firstName = firstName
        this.updateFullName()
    }
    setLastName(lastName) {
        this.lastName = lastName
        this.updateFullName()
    }
    updateFullName() {
        this.fullName = getFullName(this.firstName, this.lastName)
    }
}
 
// 基于响应式的数据,声明数据间的映射关系
// 需要维护 m 处逻辑,即复杂逻辑的数量
class O {
    @computed get fullName() {
        return getFullName(this.firstName, this.lastName)
    }
}

数据驱动的好处

如果拥有了响应状态变更的能力,也就具备了将整个应用的行为都由状态变更来驱动的条件。而由状态数据来驱动应用行为,有这样的好处:

  1. 通过比较数据的值即可验证应用的状态与行为,可以大大简化开发时的调试与测试用例的编写
  2. 可以做到应用状态的保存与恢复,使一些复杂功能的实现变得简单(如开发辅助工具、用户操作状态恢复等)

为什么不使用业界主流方案或原生 API,而是通过与 Store 绑定后使用

如,为什么不使用 react-router,而使用 router-store 以及基于 router-store 实现的路由方案,原因有:

  • 使用数据的变更驱动与外界的交互,如这里的路由读取、跳转等行为
  • 将这部分状态(如这里的路由状态)纳入到统一的状态管理方案中,好处有
    1. 同类逻辑形状的一致性
    2. 数据流向的一致性
    3. 支持推导与观测,方便其他部分使用

fe-core 采用的方案

  • 通过 Mobx 实现“透明地”(transparently)引入响应式编程范式。对比 Rx 等 FRP 框架:

    1. 避免了显式的数据封装层,读写方式与 plain Javascript 一致,使用也更简洁

    2. 舍弃了时间维度的信息,不便处理需要基于时间维度信息进行推导/响应的情况

      一个简单而典型的例子是,单选组件的当前值由用户上一次操作选中值与可选列表的 default 项共同决定,取其中更新(发生更晚)者

  • 要求将数据变更实现为 action 函数,显式地标记为应用行为,实现限制与管理

  • 将 IO 行为(网络请求、本地存储、浏览器 URL 等)映射为不同的状态实例(Store),通过修改这些 Store 的数据实现对应副作用的触发

更多内容

内容

  • store/disposable

    Disposable 类,收集对象销毁时需要执行的步骤。数据的观测底层实现依赖于事件,因此需要在对象被销毁的时候解除对应的监听逻辑。

  • store

    基于 MobX 的状态容器 Store 类,提供 disposesnapshotresume 等能力

  • fetch-store

    基于 Store 类的 fetch 绑定,将网络请求映射为数据

  • react-router-store

    基于 Store 类的路由绑定,将浏览器的导航行为映射为数据

  • storage-store

    基于 Store 类的 storage(localStorage/sessionStorage)绑定,将本地存储映射为数据

依赖安装

推荐使用 yarn 安装依赖

yarn install

开发相关

目前本地开发站点(如 financial)时无需构建本库,可直接使用源代码(ts 文件);构建用于发布 npm 包前。

npm run build # 构建 
npm run test # 测试,TODO 
npm run lint # 代码风格检查 
npm run clean # 清理构建产物 

Readme

Keywords

none

Package Sidebar

Install

npm i qn-fe-core

Weekly Downloads

1

Version

1.0.1

License

ISC

Unpacked Size

180 kB

Total Files

24

Last publish

Collaborators

  • xaomon