在组件化思想大行其道的今天,笔者接触过十余个Vue项目,无一例外都把业务逻辑写在Vue组件中,当业务逻辑复杂时,这种做法往往会带来灾难性的后果。不幸的是,几乎见不到介绍如何在Vue中编写复杂业务代码的文章。本文就是基于此背景而产生的,如有不当之处,敬请斧正。
- 业务逻辑被割裂:往往组件之间存在许多联动,例如A,B组件特定状态的变化,需要改变C组件的状态,为了追踪变化甚至要跨越五六个组件去查看代码,当你看到第四五个组件时,你还记得前面发生了什么吗?
- 无法获取调度的完全控制权:业务代码写进了 Watch、Computed,然而业务总有特殊情况,某些时刻你不想执行Watch中的逻辑,但是却无可奈何。更要命的是当一个连贯的逻辑出现在不同组件的Watch中,根本无法追踪调用顺序,毕竟人的大脑无法多线程的思考。
- 违背单一职责:由于业务逻辑没有和UI分离,当UI需要调整的时候,业务逻辑的实现往往也需要一起改动。
编辑切换为居中
把业务逻辑写在组件内,会导致蜘蛛网一样的依赖关系,无法维护
很明显,业务逻辑复杂的时候,把业务逻辑写到Vue组件中是一种愚蠢的做法,那么我期望的模式应该如下图所示,每个组件仅仅负责维护自身的UI,这样组件就会变成薄薄的一层,不同的模块是内聚的。
编辑切换为居中
添加图片注释,不超过 140 字(可选)
正如Vue官网所说的,Vue的核心库只关注视图层:
编辑切换为居中
添加图片注释,不超过 140 字(可选)
那么我们的业务逻辑应该怎么从Vue组件中抽离出来呢?答案就是Vuex。一般而言,直接在组件中写业务逻辑是“最方便”的,因为我们可以直接拿到想要的数据,但是这会导致前文中提到的问题。如果我们想把业务逻辑从组件之中剥离开来,那么我们也需要把“业务状态”也抽离出组件,那么Vuex就成了不二之选。
之前我和很多人一样,把Vuex当作是全局的状态管理器,甚至为Vuex繁琐的语法感到困扰。
但是在了解过flux的思想之后,我认为这是抽离逻辑的绝佳利器,Vuex官网甚至提供了直接从v-model绑定到Vuex的例子。
全局状态放在同一个地方,并不是说组件内所有的状态都需要放到vuex中,每个组件都有自己的局部状态。
举一个复杂一点例子,以合同审批为例:
假设合同有 1 2 3 个步骤,审批人有 A B C 三个角色,对于某个审批栏组件而言,会根据前两个条件的综合判断,组件显示不同的按钮。
对于审批栏组件而言,它的内部状态只需要负责展示界面即可,即展示 通过 退回 之类的按钮。
关于为什么会展示这些按钮的“判断”不应该放在这个按钮中,点击按钮会执行哪些操作也不应该放在这个组件中,这些是属于“业务层”的。
这样做有什么好处呢?
- 单一职责:修改视图时不会影响“业务逻辑”的判断,修改“业务逻辑”时不需要修改视图层。
- 可复用性:如果两个页面的业务逻辑不同,业务逻辑写在组件内部,很难在两个页面之间复用同个组件。
- 可维护性:独立的领域也让从需求到代码实现中出现的错误更容易排除,让新手理解起来更容易。
- 可测试性:领域代码是纯净的,测试一小块功能不需要模拟整个系统。
那么应该怎么落地呢,答案是“整洁架构”,我发现这是比较适合在前端落地的架构。