现在来说说组件,组件作为view层应该尽量保持简单:

组件应尽可能无状态

所有的状态都在store层,组件只是消费这些状态和用例函数(或是发事件)。尽量不要有私有状态:

  1. 私有状态的维护必然走具体框架的api,这导致了view层较高的迁移成本。
  2. 私有状态外部是无法修改的,当然这是私有状态的本意,不过随着产品的更迭,很多私有状态需要外部(或另一个地方)来修改它,为此不得不把它迁移到store,这是笔者遭遇过很多次的情况。如此以来,倒不如不要私有状态,全走store。

这样组件只是作为模板,很好的弥合了框架之间的差异,甚至框架都变得必要性不大,仅需要一个虚拟dom就可以构建数据驱动的现代程序。

组件应不关心业务细节

组件读取和提交的颗粒度应该是实体或值对象,而不是它们属性,由应用层来感知必要的细节。

  1. //bad 组件要知道用id来做删除
  2. <button onClcik={() => app.删除待办(todo.id)}></button>
  3. //good, 颗粒度是实体,组件无需知道删除相关的细节
  4. <button onClcik={() => app.删除待办(todo)}></button>

这样的好处是组件和用例层解耦了,应用层的变动(比如现在改用key来做删除)不会影响组件,同时也避免了参数不够来回修改的情况。

不必在组件之间传递业务数据,组件直接对接store和应用层

redux等库提倡有只在顶层connect store,然后层层传递给子组件。这样做的坏处是层层传递带来的大量样本代码,大量的命名和类型声明,层层传递过程中如果改了名,对于维护性也有很大损害。其实是不必要的,因为状态都在store层,函数都在都在应用层,底层组件可以直接import这两层的数据和方法:
点击查看【processon】

你可能会说这样组件不是没法复用了吗?对于这个问题,我是这样认为的,组件的作用有两个,一是复用,一是分治。对于业务性组件,大部分情况下复用的几率很小,在不需要复用的情况下硬写成可复用组件只是徒增成本罢了(况且,后面再改成复用性组件的成本也不大)。当然,确定需要复用的还是按复用性组件的写法,从props传入。 react出现以来,大部分人都不由自主的提高了组件在心中的地位,用各种模式来保证组件的复用性和拓展性。不过在本架构里,只要用例是有价值的,不过多关注组件的复用性,在复杂场景下,复用性的组件意味着大量的if else,我不认为这是种好的方式。 本架构倾向于把组件当模板用,除去业务无关的通用组件(此类组件一般被ui库实现了),业务组件尽量不考虑复用性,它们最好复用的方式可能是复制粘贴。另外,页面级组件永不考虑复用性

这个做法好处是,组件父子之间几乎没有props传递,它们仅仅是组合关系。在组件编写上由于无需层层传递,层层声明,层层命名,编写效率提高50%以上:

  1. //bad
  2. import app from 'todo/app'
  3. //TodoList
  4. {todos.map(todo => <TodoItem todo={todo} onDelTodo={app.删除待办} onToggleTodo={app.切换状态} />)}
  5. //good
  6. import app from 'todo/app'
  7. //TodoItem
  8. <button onClcik={() => app.删除待办(todo)}></button>

当然这是一个偏激进的做法,读者可以自行斟酌要不要采用,对架构整体没有任何影响。