前端开发的玄学之开发的意识流——前言 - 掘金 (juejin.cn)
前端开发的玄学之开发的意识流——基座 - 掘金 (juejin.cn)
前端开发的玄学之开发的意识流——模块开发(一)前端的工作内容 - 掘金 (juejin.cn)
前端开发的玄学之开发的意识流——模块开发(二)评估开发时间 - 掘金 (juejin.cn)
前端开发的玄学之开发的意识流——模块开发(三)怎样开发 - 掘金 (juejin.cn)
第二部分 模块开发
等等,怎么现在就开始了呢?我还没开始安装环境,还没看⽂档呢,还没看设计稿!我们不关注这些。
当然了,我们也本内容也会很少讨论与人的关系,人与人的关系————更加玄学(我之前的文章有一些涉及)。
这部分主要讨论三个部分:
-
前端是做什么的
-
怎么评估开发时间
-
开发的方式
1. 前端的工作内容
我们不考虑、不讨论前端对于业务的作用
这个小标题是不是有点不知所以?来个Wikipedia的答案:前端Web开发是通过使用HTML、CSS和JavaScript开发网站的图形用户界面,以便用户可以查看该网站并与之交互。看起来,只需要简单的会三大件就可以了,但是,这句话里面其实隐藏了很大的一个坑——交互,以及,丢失了一个重要的信息——数据。
前端 = UI + 数据 + 交互
在以往的工作中,大家描述前端开发都是“将服务器数据展示出来,并且接受用户输入”。这里,个人觉得,即使是前端开发者,也都会认为前半句是重点——“将服务器数据展示出来”,因为前端不就是“展示”么?即使觉得交互重要,也会“选择忽略”,因为细节太多。而个人经验看来,正是后者,将一切变得不可预估,变得难以把控。
这⾥我想引⼊⼀个模型:
左图,是⼤多数⼈认为的前端开发;右图,是真实的前端开发。你可以⾃⼰脑补下你碰到的这些场景。
为什么会这样???都是因为,交互——这个幽灵的加⼊。记得react作者的⼀个分享,“以前”的前端之所以简单,就是因为“⼀次更新,刷新全部”。
交互,是万恶之源!
UI部分
UI即界面,是处理用户输入输出的图形接口。这里暂时无法考虑动态的内容,在项目真正动起来时,很多实现就不一样了。在纯静态的展示下,我们遇到的问题有这些:
-
UI定位问题:UI图一般是绝对定位,实际开发时需要不断的拆分、嵌套以及相对定位,这导致即使静态页面想复原UI图也需要时间。
-
CSS样式复用问题:设计师提供的CSS样式每个节点都是单独控制的。前端开发过程中需要考虑CSS的复用问题和继承问题。UI包含了设计师、产品经理各种权衡利弊,是他们内心深邃思想的结晶,不可能不参杂主观实践。
-
UI组件重用问题:尽管UI设计师也会设计基础的组件结构,但对于相似组件,常因认为是简单而忽视了实际的差别。读者可以尝试用一个UI框架去实现另一种UI框架的UI,体会其中的挑战。
-
组件库接口不足:基础组件库对于动态变化内容的接口提供不足。例如,使用element-ui时,设计师提供的UI组件基础结构有变化,可能会造成大量的开发工作。
-
动态内容显示规则问题:UI图少考虑动态内容的变换,如表格内字数不同导致的显示规则差异。
-
字体还原难度:字体还原难度较高,宽度是动态的,对齐方式多样,存在baseline问题,包括英文、汉字以及大小写。
-
其他种种
还原UI最好的办法是绘制一棵显示树,尽量按照“模块化”的方式,将页面“分而治之”。这里的前提是这个页面是一个简单的、没有用到全局UI的、纯粹的页面,否则很难画出一棵纯粹的树。
这⾥已经是⾮常简单的⼀个“⻚⾯”了,⾥⾯的div(这⾥代指所有的htmlElement,设置你可也可以将div假象成
模块或者组件)在真实的项⽬中,算是⾮常少。
在实际项目中,为了构建这棵树,我们不自觉地会采用“组件化”编码。但在我接触的项目中,由于以下两个原因,想让大家一起构建的“树”长得一样,非常难:
-
UI组件的不确定性:
-
a. 实现手段不确定,如普通按钮可以是扩展原生的,也能是一张图片自定义的。
-
b. 划分逻辑不确定,例如上图中的某些div可能没有存在的必要。
-
-
UI生成规则的不确定性:
-
a. 按钮可以是普通按钮、图片或者文字。
-
b. 居中布局可以采用transform、flex,或者通过JavaScript动态计算。
-
c. 存在各种伪类和伪元素的考量。
-
数据部分
前端数据是服务于前端展示的,与服务器数据有着本质的不同。事实上,前端数据主要存储在内存或者浏览器缓存中,存储空间有限,它们主要用于前端展示。对于信息的采集,例如报错或用户画像信息,这些数据需要上传至服务器,才能供运营人员使用。
按照是否受前端同学掌控,数据可以分为两类:
-
前端内部数据:这一章节我们讨论的基本上都是这一块,它完全由前端同学掌控,不需要关心来源于服务器的数据,也不需要关心我们需要提供给服务器的数据。在这里,服务器人员是额外的。
-
服务器数据:在当前所谓的“前后端分离”的大背景下,服务器数据反而成为了前端开发的心智负担。通常,很难把控他们提供了什么,也很难改变我们需要提供给他们什么;在大多数情况下,我们需要适配他们所提供的,满足他们的需求。
对于前端内部数据,我们可以从多个维度进行划分:
-
按照动静划分:
-
静态数据:例如输入框的
placeholder“姓名”,一般写死在HTML文件里面。(如果页面都是这种数据就好了,比如以前的博客,实现起来“非常简单”。) -
动态数据:需要根据用户交互来动态设置的,比如用户信息,这些信息需要前端开发人员进行精心维护。这一块,就非常“玄学了”,大量的前端开发工作都是围绕这一块来展开的。这里也跟交互息息相关。
-
-
按照影响范围来划分:
-
全局数据:全部组件可以访问的数据。
-
局部数据:只被当前组件管理的数据。比如,在上图中,页面数据、组件数据我们都认为是局部数据。
-
传送门数据:这个名字起得好,非常形象。有些数据需要在组件之间穿梭。全局、局部数据都是比较“容易”管理的,而这里的“传递”,则需要各种微操。例如,上图的两根红线,需要将各自的数据进行传送——这非常难,非常难把控!
-
-
按照是否持久化划分:
-
持久化数据:包括状态重建,减少服务器请求的数据,服务器鉴权数据,如cookie、token,操作记录,某些软件需要undo、redo等,以及需要页面共享(通讯)的数据,比如用户信息。
-
非持久化数据:包括页面静态信息和服务器动态返回的展示数据。
-
假设,没有上面提到的“动态数据”,“传递”数据,“持久化数据”,那么,这里我们已经可以满足外部人员对于前端的幻象了,“只是把数据展示出来”。然而,实际上,状态的不断变化才是前端开发最“玄学”“最难”的点。过程是展示数据(状态)生成的中间环节。
问:什么是“状态”?这里的状态不是单单只定义的变量,服务器返回的数据,我认为,变量是状态,页面的静态展示是状态,服务器数据也是状态,所有需要付出心智成本的,都是状态!!!因此,建议读者补充一下状态机,看看“状态”是一门怎样的玄学。
交互部分
终于,要说到交互这个天坑了!
上面讲数据的时候,我已经很难把数据说清楚了,不得不在结尾开始讲“玄学”。我很难描述交互,我也只能给一个简陋的定义:交互就是对于用户的输入进行反馈——交互就是反馈?貌似是一个病句。交互,产生的异常实在是太多了!
这里,我只能从“状态机”思想来解释交互了。我认为,交互是状态机模型中的输入。从一个状态迁移到另外一个状态,是用户想要的结果。而触发这种结果的输入,叫做交互。
状态机有几个元素:
-
状态
-
事件(或者也可以叫做输入)
-
转换
交互,在微观上,其实就是一个状态机。但是,在宏观上,又打破了状态机。比如,状态,在宏观上甚至都很难定义出来“状态”,很容易出现“伪态”。而且,由于状态机太过于底层,在Web UI层面,它可以被各种理解,可以从不同维度来划分。
为了方便解释“实现交互”前端需要做什么,我只能先忽略“状态”的定义,划分。而对于第二点第三点,我也只能说从稍微具体的角度来说一下。由此,我认为:交互是实现状态机中的“事件”与“转换”。
常用的事件(输入)有哪些?
-
外部的,不由前端业务开发人员把控的: a. 网络加载; b. 服务器接口,由于这个是与人打交道的,服务器接口与前端接口数据结构不一致问题,非常容易造成的额外的成本,负担;还有异步操作的问题;
-
内部的,可以被前端完全把控的: a. 浏览器的: i. 刷新,这个事件可以打断当前的所有状态,所有内容都要重建,造成所有内部流程控制全部失效,相当于一次“宕机”,一切内存内的状态全部丢失。刷新有可能是强制刷新,路由跳转,页面崩溃重建; ii. 缩放; iii. resize; iv. 缓存; b. 鼠标的: i. 点击,拖动,滚动,滑动; c. 键盘输入; d. 其他: i. 其他传感器; ii. 自定义事件,这个也非常容易出现失控,很神奇的一个条件; iii. 路由跳转,浏览器跳转,编码路由跳转; iv. 禁止状态:禁止状态会影响很多交互内容; v. 内存与缓存; vi. 异步; vii. 状态联动。
我想到了一个词,事务:
-
原子性(Atomicity):事务是数据库的逻辑工作单位,事务中包括的操作要么全做,要么全不做。
-
一致性(Consistency):事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
-
隔离性(Isolation):一个事务的执行不能被其他事务干扰。
-
持久性/永久性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
各位前端小伙伴,大家看一下,这里是不是大家在实现交互的时候,如果能够符合以上特征,就会让交互变得相对简单很多?
而事实上,交互则具有“反事务”特征:
想象一下,需要状态转移的时候,我们为什么最喜欢全局模态
-
很难全做、或者全不做;
-
结果不可预测;
-
容易被外部打扰;
-
很难持久。
交互具有状态机的特征,但是非常难以建模,只能从宏观描述,甚至,数据究竟是状态还是事件,都非常难以琢磨;交互具有“反事务”的特征,造成非常高的心智成本。
这里给一个项目中的例子:页面1与页面2有联动。
结语
最终,我们回到前端是做什么的这个话题上。总结一句话:构建用户界面,处理数据展示和交互逻辑。