Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

再谈前端状态管理 #16

Open
winixt opened this issue Aug 22, 2021 · 0 comments
Open

再谈前端状态管理 #16

winixt opened this issue Aug 22, 2021 · 0 comments

Comments

@winixt
Copy link
Owner

winixt commented Aug 22, 2021

俗话说得好,程序 = 数据结构 + 算法。我们前端页面其实也可以简单抽象成:数据 + 逻辑。数据通常为服务端数据,逻辑可以分为两大类:无状态逻辑和有状态逻辑。

无状态逻辑,可以是公众函数、公共业务逻辑、service 处理器,因为是纯函数,可以抽象出来到处复用。

有状态逻辑,又可以分为两类:多实例有状态逻辑和单实例有状态。多实例有状态逻辑,本质上更偏向于无状态逻辑,具象一点可以理解为 vue3 composition API 和 react 的 hooks。前端应用大部分逻辑可以是无状态逻辑和多实例有状态逻辑,比较好处理。复杂的是单实例有状态逻辑。状态管理要解决的问题,也是单实例有状态逻辑的增删改查问题。下面来仔细分析一下。

单实例有状态逻辑,又可以分为,单实例非共享状态逻辑和单实例共享状态逻辑。

单实例非共享状态逻辑

单实例非共享状态逻辑,指的是状态在一个地方展示,可以背多个地方修改。为了方便说明,这里以A组件为中心:

  1. A 组件的子组件要修改 A 组件的状态

  2. A 组件的子组件的子组件(以及子子…组件)需要修改 A 组件的状态

  3. A 组件的父组件需要修改 A 组件的状态

  4. 其他情况

    1. A 组件的父组件的父组件(以及父父…组件)需要修改 A 组件的状态
    2. A 组件的兄弟组件需要修改 A 组件的状态
    3. A 组件的兄弟组件的子组件(或父组件)需要修改 A 组件的状态

场景一:A 组件的子组件要修改 A 组件的状态

代码内聚性通常意味着可维护性越强,这个时候子组件通过暴露事件出去给 A 组件使用会是一个比较佳的方式,或者传递方法给子组件。

场景二: A 组件的子组件的子组件(以及子子…组件)需要修改 A 组件的状态

层级嵌套过多,通过暴露事件的方式一层层往上浮动,写起来繁琐,事件名称有变动得到处改。不建议事件传递的方式。有两种方式可以考虑:

  1. 如果子组件的子组件相对独立,可以将子组件的子组件抽离出来,作为 A 组件的直接依赖组件,类似于常见的:Form 和 FormItem 的关系。
  2. 在 1 不满足的情况下,用 provide/inject,直接夸组件传递。

场景三:A 组件的父组件需要修改 A 组件的状态

这种情况下出现的情况相对还是比较多,通常我们会用 ref 解决。但也要尽量控制,用 vue3.2 的 script setup 会比较好,可以明确制定导出的方法。

场景四:其他场景

因为该数据只在一个地方展示,却在八杆子不着的地方修改了,这时更应该考虑交互的合理性。在交互合理的情况下,考虑组件划分非合理性。确认交互没问题的前提下,组件划分没问题的情况下,可用发布订阅模式,或者采用下文介绍的抽离共享状态的方式。个人偏向于后者。

单实例共享状态逻辑

单实例共享状态逻辑,指的是一个状态在多个地方展示。为了方便说明,这里以A组件为中心:

  1. A 组件的子组件要共享 A 组件的状态
  2. A 组件的子组件的子组件(以及子子…组件)需要共享 A 组件的状态
  3. A 组件的父组件(或父父…组件)需要共享 A 组件的状态
  4. A 组件的兄弟组件(或兄弟组件的子子…组件、父父…组件)需要共享 A 组件的状态

场景一:A 组件的子组件要共享 A 组件的状态

props,单项数据流,经典场景。

场景二: A 组件的子组件的子组件(以及子子…组件)需要共享 A 组件的状态

层级嵌套过多,通过 props 的方式一层层往下传,写起来繁琐,名称有变动得到处改。有两种方式可以考虑:

  1. 如果只是子组件的子组件,层级不深还是可以考虑 props。
  2. 如果子组件的子组件相对独立,可以将子组件的子组件抽离出来,作为 A 组件的直接依赖组件,类似于常见的:Form 和 FormItem 的关系。
  3. 在 1 和 2 不满足的情况下,用 provide/inject,直接夸组件传递。

场景三:A 组件的父组件(或父父…组件)需要共享 A 组件的状态

考虑两种场景:

  1. 如果状态相关逻辑相对 A 组件较为独立,可以考虑状态往上提。
  2. 如果状态相关逻辑和 A 强关联,或者不仅仅和A 强关联,在组件划分合理的前提下,如果可遇见的类似逻辑不多,可用 readonly 锁定状态,进行状态共享,否则直接用 vuex。无法判断的话直接用 vuex。

场景四:A 组件的兄弟组件(或兄弟组件的子子…组件、父父…组件)需要共享 A 组件的状态

处理方法和场景三一致。

@winixt winixt changed the title 在谈到前端状态管理 再谈到前端状态管理 Aug 22, 2021
@winixt winixt changed the title 再谈到前端状态管理 再谈前端状态管理 Aug 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant