react项目开发—关于代码架构/规范探讨

社区一直讨论的一个主题,到底是react好,还是vue好?

我的答案

本人对这个问题的答案是这样的:

1、react给了我们更大的自由度,我们可以以任意的方式,组建我们的代码结构,我们可以操控的代码细节更多,也就能在更多的细节上面,对我们的代码进行更细致的优化。

2、react在书写的过程中,驱动我们对数据、UI有更清晰的认知。我们必须对他们的运行细节,ui变化,数据流向,有明确的认知边界,才能对我们的项目,进行清晰的掌控。

3、vue2,它是死板的,明确的定义了数据的申明在哪里,生命周期在哪里书写,函数和事件在哪里书写,我们几乎很少有可发挥的空间。

4、vue2,数据的双向绑定,让我们可以忽视数据内部真正的变化边界,我们需要的时候,直接无脑赋值就能得到我们想要的结果。

导致的结果

这是这两个框架,不同的api,给我们的客观印象。同时因为团队的差异,它们又导致了一些问题。

1、react框架的项目开发,它注重细节,注重每一个数据的驱动,这就导致了,用这个框架的前端团队必定要有一定的极客精神。它的过度自由,导致了我们甚至可以随意定义我们数据的管理规范、组件的划分、甚至任意的代码结构。

但是,这正是一个团队最可怕的东西。它导致了不可控。

2、vue2的项目开发,它是简单的,容易上手的,并且它就是一个固定的写法规范。

  • 它的vue文件,就是由标准的html、js、css三部分构成。
  • js里面,数据定义,生命周期,函数和事件,都有固定的地方。

这是vue2作为一个框架的缺点,代码可以控制的比react少,书写代码的细节上,性能可控性小。但是,作为团队视角,它提供了一个团队最重要的东西------相对简单、相对可控。

React项目,我们可以从哪些方面提升代码的水准

评价一个项目的代码水平到底好不好,有这么几个方面。

1、代码性能和质量。

代码性能和质量,有些是项目工程层面的内容,有些是代码实现方面的内容。

项目工程层面:代码包的体积大小、首次加载的效率、首屏渲染时间、用户可操作时间。

代码实现方面:渲染效率、是否卡顿、大数据量的处理、虚拟列表、图片加载、分块渲染等等。

2、代码整体的层级划分

目前,现阶段的大多数前端,能做到的基本的目录结构划分,也就是我们的src下面,有这么几个主体目录:

  • index.js/index.tsx,整个应用的入口文件。
  • router,整个应用的路由配置文件。
  • pages,整个应用的页面层级组件,一般router中的一个path,就对应这里的一个组件。
  • components,全局的基础组件。
  • service,api请求相关的服务封装。
  • redux,整个页面的数据管理存储。
  • utils,全局某些通用能力/配置,放置在里面。
  • assets,全局资源文件(图片资源、静态js库、svg、字体文件等等)

以上基本上是每一个前端工程的共识,但是除此之外,我们应该还有其他的共识。

1、页面pages,尽可能的组装业务,进行集中的资源调度。

也就是,我们尽可能的把业务相关的东西,都往pages层次的组件进行集成。

当我们从路由中,得到这路由对应的pages,往往预示着,它是一块相对独立的业务。比如:文件列表页、文件详情页等等。而对于人类而言,在一处地方看代码,比在多处看代码,更容易。

2、页面pages,尽可能的进行统一的数据管理。

在pages层面,进行统一的数据管理,数据管理往往是这么几种情况,从redux接入全局数据进行管理,向pages调度的子组件,通过props传递数据,或者针对Provider全局数据的注入的使用。(至于为什么,可以继续看下面数据管理部分)

3、页面pages,在拆分组件的时候,层级不应该过于多。

在pages的组件层面,很有可能,我们会遇到非常复杂的业务,导致我们的pages层面的组件,变得非常臃肿,这个时候,我们需要进行组件拆分,但是我建议,再只多拆分1层业务组件,不要拆分多个不同层级的组件。组件的层级过多,数据通信的复杂度就会提升,代码的可读性就会降低,如果这个时候,再配合不好的数据管理习惯,屎山代码,就已经形成了。(具体是为什么,可以继续看下面的组件拆分部分)

4、 每一个单元应具备原子性

pages层面,调度的每一个单元,应该具备一定的特性---原子性。

一个函数,只完成一件事情,比如事件响应,数据处理。

一个组件,它是纯粹的,它只和传递给它的props有关,和其他无关。

一个业务组件,也就是在pages过于复杂的情况下拆分出去的组件,虽然它具备业务属性,但是对于pages来说,它也是相对独立的。

3、组件的层级划分

个人比较推崇的组件层级划分方式:

  • pages层,pages层很简单,就是代表页面的意思,每一个路由path,它都对应一个page。
  • 业务组件层,一个page,很有可能很复杂,我们需要一定的设计,把这个页面分成几个块,然后由pages统一调度,实现我们的业务。
  • components层,也就是纯粹的UI组件,它只和props有关系,和其他无关。全局任意的地方,都可以调度。

为什么这么拆分呢?其实这是这么多年,针对真实业务场景,综合思考下来,得到的比较好的实践方式,形成这个组件划分的原则,是基于以下几个方面的思考。

1、辨识度高。

每一个路由,对应一个pages组件。

每一个components中的组件,都有与业务无关的纯UI组件。

根据业务的复杂度,中间产生了一层业务组件。

每一种组件,各司其职,边界清晰,方便我们看到一个组件,就知道这个组件是干嘛的的一种标识。

pages层的组件,进行统一的调度,数据管理,对接redux,组件拼接,事件交互等等。一个文件中的代码,阅读起来,也更加的容易。

业务组件,当pages层的组件,过于复杂的时候,我们把业务相对独立的单元,拆分出来,形成我们的业务组件。业务组件是可以对接redux,也可以有自己的数据状态,各种事件交互。(业务组件的核心,在于如何巧妙的进行边界设计,具体请参考下面的业务组件层的拆分思路)

components层的UI组件,纯粹的UI组件,与业务无关,在全局可复用。

2、结合业务拆分、代码可读性、复用性的一个综合结果。

多数情况下,我们可能没有一个清晰的思路,去做组件的划分工作。

遇到复杂的业务,我们本能的就进行组件的拆分,当时写的时候,没有考虑太多,但是写到一半,会发现,这个组件的变动,可能会引发其他组件的数据变动,我们就遇水搭桥,见招拆招,有些用redux解决,有些用props父子传递数据进行通信。

保持这样的习惯,我们可能拆分一个又一个组件,props传递了一层又一层,等过一段时间一看,自己都看不懂,自己写的代码是啥。

这是本能的,不想思考的,总想简单化的把项目完成。但是往往导致的结果是:本来简单的项目,代码写的越来越复杂!!

pages层面,负责数据的整体管理,组件调度,那么我们的通信就会比较方便,相当于pages层就是这个页面相关的业务的通信中心,我们基本上,能够通过props父子组件传递消息。

props父子组件,传递消息,注定了组件的层级不能过多,过多就会导致,数据就像套娃一样,一层又一层,导致可读性降低。

业务组件的出现,是为了解决,过于复杂的页面业务,我们可能需要进行拆分,把能够单独拆分出去的结构,独立出来,这样不仅从业务上进行了模块的拆分,也能提高不同模块的代码可读性。

那么,业务组件层的拆分思路是什么呢?

3、业务组件层的拆分思路

其实原则上,这里需要我们进行深入思考,哪些模块是独立的单元?页面中的哪些模块,和业务主体通信较少?

这其实就是核心,代码倒逼我们进行设计,进行深入思考,进行深入的业务理解。

思考点1:某一个模块,是不是相对独立的UI模块?

思考点2:某个模块是不是单独的业务单元?

思考点3:某个模块拆分出去,通信的代价到底大不大?

思考清楚这些,其实本质上,你思考的是,你的代码架构问题,你以什么样的视角,来解读你的UI、数据、业务的关联关系。

有了这些思考,你一定可以拆分相对合理的业务组件层。

4、数据管理的划分

多数前端,写代码的时候,并不会有数据中心,数据流向这些概念。

很多人还停留在,完成UI,渲染数据的层面。

如果是这样的思路,无论是组件划分,还是数据管理,注定做的一塌糊涂,代码成屎山是必然的。

组件划分的思路,其实也是一种数据管理的思路。

1、pages层,从天然的业务视角来看,他天然就是一块业务的集合,所以pages层作为一块单独的业务数据中心,它天然合适。

2、components层,我们定义了它,只和props相关,和其他无关,它被其他组件调度,天生注定了它通过props传递数据的行为模式。

3、业务层组件,我们定义了它是pages下面的一块单独业务,我们有必要对它进行合理的设计,它与pages组件的关系,是主模块与子模块的关系。可以通过props通信,也可以接入redux通信。

4、redux,大多数情况下,我们其实不需要用它,当数据的通信,不满足业务场景的时候,redux就是我们的解决方案。它真正的业务价值,在于跨pages的通信。比如,某个页面状态的更改,另一个页面状态,也跟着更改。

redux另一种常见用法:

redux的特性,在umi或者其他框架中,把redux作为数据管理中心来使用,所有的页面状态,业务相关的数据,都定义在redux中,所有的接口请求,用户行为,都是通过redux的dispath进行触发行为,来更改数据,数据通过props流入各个组件中。

这种方式,其实也是各种推崇的一种方式,但是这种方式对人的要求也高,表明了我们团队中的每一个人,都要熟悉并且接受这种数据管理的方式,才能写出相对一致,可读性高的代码。

只要其中的一部分人,不接受这样的数据管理方式,代码的管理它就会变得混乱,有些初始化数据,可能在pages组件中,有些可能发生在redux层,作为阅读者,很难排查代码执行的路径。

现实场景说明:

我们大多数情况下,对于redux的使用,并不清晰,redux的使用,是混乱的。

本不必要的数据,可能放在redux中管理。

本不必须接入redux的组件,非要接入redux。

redux中的dispath,调用的地方,千奇百怪。

数据的流向定义,完全杂乱无章。

这些东西,对于一个项目,都是灾难性的影响,它会导致,我们代码的迭代难度,急剧上升。

相关推荐
二木一夕3 小时前
Vue 3 的组合式 API和传统选项式 API区别(vue2转vue3,两者差异)
前端
LuckySusu3 小时前
【vue篇】Vue 项目中的静态资源管理:assets vs static 终极指南
前端·vue.js
LuckySusu3 小时前
【vue篇】Vue.delete vs delete:数组删除的“陷阱”与正确姿势
前端·vue.js
LuckySusu3 小时前
【vue篇】Vue 模板编译原理:从 Template 到 DOM 的翻译官
前端·vue.js
小菜摸鱼3 小时前
Node.js + vue3 大文件-切片上传全流程(视频文件)
前端·node.js
LuckySusu3 小时前
【vue篇】Vue 2 响应式“盲区”破解:如何监听对象/数组属性变化
前端·vue.js
LuckySusu3 小时前
【vue篇】Vue Mixin:可复用功能的“乐高积木”
前端·vue.js
洋不写bug3 小时前
前端环境搭建,保姆式教学
前端
需要兼职养活自己3 小时前
react高阶组件
前端·react.js