聊一聊前端框架

一、为什么需要前端框架

关于前端的框架,这几年发展迅速,最早的是以页面html为单位进行的前端开发,使用html来展示页面元素,使用css来给元素添加一些自定义的样式,使用js来给页面添加一些动态的效果及操作,这种方式的前端其实严格意义上都不能算是端,更无法称之为是应用了,所以这个时候的前端就只有一些静态的文件放在后端项目中。随着互联网的发展,对于前端的需求越来越多越来越复杂,难以通过几个静态html页面的方式去承载我们的需求,而且最关键的问题就是效率和性能的问题,所以前端出现了工程化的理念,页面转变成了一种应用,很显然,前端这种以页面为单位,所有元素都放在一个html文件中的方式显然已经不适用了,这个时候就出现了组件化模块化封装化等等的需求,出现了各种各样的框架。


二、模块组件化方式

现今前端框架中组件化的方式已经逐步成为主流方式,在这些模块化框架中,组件树的概念出现了,比如像Vue、react等框架都有相对比较完备的组件化的概念。组件可以是某个功能模块的抽象,可以是公共操作的封装,甚至组件也可以是一个函数,比如像react中对组件函数这个概念就比较明显。

在实际应用中组件是可以分类的:

1、纯展示型的组件:就是数据传进去,帮你渲染DOM

2、接入型组件:这种组件可以说是在展示型组件的上层,它会与数据层交互,会将数据向下传,传给展示型组件

3、交互型组件:是对与表单组件的封装和加强,比如elementUI里的表单组件,比较复杂,可复用性强

4、功能型组件:比如在Vue中的路由router组件,它不渲染任何的DOM,而是作为一种抽象机制


三、声明式渲染机制

在Vue中模板的概念让更少的逻辑放到视图中,逻辑少的模板更能体现视图化的思考。现在最重要的渲染就是声明式的渲染方式,以数据为驱动更新视图,这种方式其实数据和视图是相互独立的,两者更像是建立了一种映射关系,通过数据状态变化去响应,说白了就是不需要去操作DOM了。最开始的时候是一种命名式的方式去直接操作DOM,就是通过各种js的函数去获取DOM对象然后操作它,这种方式不具备一种抽象的思考方式,所见即为所得,需要操作哪个就直接搞哪个,这种方式十分简单粗暴,给人的感觉就是很重很暴力,对于一些稍大一些的应用来说就会显得层次结构混乱难以维护。而现在主流的这种声明式的渲染方式就显得轻巧的多,层次清晰易于维护。


四、变化侦测机制

在Vue中数据是响应式的,把数据交给Vue时,Vue会进行转化,当数据改变时,Vue会侦测到变更。这种变化侦测的方式主要可以分为两种,pull和push。pull是一种粗粒度的脏检查机制,这里系统实际上是不知道有哪些数据发生变化了,它需要一个信号告诉系统数据可能要发生变化,此时系统会去暴力比对所有的数据,检查出是哪个数据发生变化了。而push则是一种粒度比较细的检查机制,速度更快,定位更加准确,但是细粒度的机制系统开销比较大,比如内存开销就比pull要大。所以在选择这种侦测机制时,不存在绝对的好与坏,可能不同的场景不同的系统环境不同的业务需求会对其有不同的要求。所以在Vue中,它选择了一种折衷方式,就是一种混合使用,组件里使用push,每个组件都是watcher,内部使用虚拟DOM进行比较。


五、状态管理

状态管理是由Facebook首先提出的,在状态管理上React逐渐合并到了Redux上,而VueX实际上一定程度上受到了Redux的影响。状态管理的本质是从元事件映射到状态的迁移与改变,再映射到DOM UI的变化,就比如说,用户点击一个按钮到点击事件被触发的这个过程。在这里,上面说到的声明式的渲染方式实际上已经帮我们解决了从状态到UI这一块的变化映射问题。状态管理实际上就是为了解决如何管理将事件源映射到状态变化的过程,如何将映射过程从视图组件中剥离出来,提高可维护性。在Vue里它体现了一种范式的思维方式,数据是响应式的,框架已经在数据上做好了声明式副作用的声明。可变数据难以维护是当我们手动操作数据副作用操作,手动观察时会带来一定维护上的成本。关于状态管理中的异步问题,Redux是将它交给MiddleWare去做,VueX是在action里做的。纵观目前的这些状态管理的方案,其实还是有痛点的:组件的局部状态和全局状态如何区分?个人觉得没有很明显的界限。


六、路由

路由的问题是大型单页面应用才会遇到的问题,传统的路由思想是一种侵入式的方式,比如说之前写应用时得先从路由开始写起。当React和Vue这种专注于View层的框架出现后,我们不难发现把组件和路由解耦是完全可行的,而且更加的灵活易于维护和迁移。其实从组件出发再来思考路由的问题,本质上就变成把一个URL映射到组件树结构的一个过程。这里从URL到组件的映射有一些小的问题,到底应该从URL出发还是以状态出发?比如说一些路由库的实现是以状态之间的迁移为核心的,但其实也可以把URL理解为一个序列化的状态。

最简单的路由其实就是一个动态组件,在这里其实还是有很多问题的,比如重定向、别名、懒加载的问题,还有路由的钩子跳转如何应对用户取消跳转无效的情况等等。现在主流的路由方案都差不多,原理基本相似,目前最新的一种方案是用组件本身路路由的思想,这就和上面提到的功能型组件的概念有点契合,在父组件里可以声明式的渲染其它组件。


七、CSS方案

对于现在应用的CSS有几种比较主流的方案

1、CSS与JS完全解耦,靠预处理器和一定的规范来保持可维护性,这是比较传统的方式。

2、CSS Modules,依然是CSS,但是通过编译来避免CSS各种类名的全局冲突。

3、各种CSS-in-JS方案,比较激进。

4、Vue单文件组件CSS的方式,是一种比较折中的方案。

其实在选择CSS方案时首先要明确场景的问题,如果应用逻辑已经组件化了,是一个比较复杂应用的开发时,那么传统的CSS方式就是上面的第一种可维护性就比较差了,那么把组件和结构同义化是减低思维负担的一种方式。跨平台复用我们可以把静态的CSS PASS后编译成跨平台的JS。


八、构建工具

传统的前端开发方式其实是没有构建这一说法的,也没有编译的过程。而现在的前端开发时需要安装很多的开发工具,原因是现在的Web能力越来越强,外部需要越来越高,因此我们需要这些工具的辅助。

构建工具解决的其实是这几个方面的问题:

1、任务的自动化。

2、开发体验和效率(新的语言功能、特性、语法糖等)。

3、部署相关的需求。

4、编译时的优化。

现在比较主流的构建方式就是npm script+Webpack这种方式。前端的开发其实都有一个限制那就是最终的代码不可避免的要运行在浏览器中的,在我们使用技术的新特性时就要考虑这个问题,所以构建工具链渐渐完善起来了。

Webpack其实很复杂,原因是因为它要解决的问题就很复杂。它看起来只是代码打包工具,其实仔细想想会发现部署优化里要做很多很多事情。比如JS中静态资源的内联,不同资源刷新版本时如何缓存,如何代码分割,其实Webpack在这里帮我做了很多繁琐的“前端运维”的工作。严谨的前端工程肯定要走编译构建这处过程。


九、跨平台

从前端框架的角度看,跨平台渲染本质是在设计框架的时候要在框架的渲染机制和DOM解耦,并不一定使用虚拟DOM。其实说到底本质上只需要把框架更新时结点操作封装起来就可以做到跨平台了。比如,VueX本质是在底层针对每个平台有一个适配的渲染引擎,只要把渲染引擎暴露的结点操作的API跟框架运行时对接一下,就可以实现将框架里面的代码渲染到原生应用上去了。


十、总结一下

其实不管是什么框架还是什么技术,其实都是先发现问题,再有解决问题的想法和思路,当然这个过程肯定有平衡和取舍。比如上面刚开始提到的为什么传统的前端开发方式已经不适用现今的应用需求了,就是因为传统的方式暴露出各种各样的问题,所以才导致各种前端框架各种解决方案的出现。不管是什么技术方案其实都有它的亮点和痛点,在选择衡量技术方案的时候,应该去思考这个技术背后是在解决什么问题,它到底能为你和你所做的事带来怎么样的帮助和促进,这样一方面可以帮助我们更好地理解和使用这些技术,也为以后哪天如果遇到业务中的特殊情况,需要自己做方案的时候打好基础。

在学习一个技术框架时,其实我个人认为最重要的是理解这个技术背后所表现或者实现的设计思想,因为技术其实是局限的,而思想是可以衍生和发散的,其实很多的技术方案它们背后的思想可以说都是殊途同归的,都是可以找到相似的地方。在前端框架上,我们不能止步于仅仅只是使用框架写代码的层面上,应多在组件化、设计模式、模块化、数据流、渲染机制、路由机制、构建方面还有代码标准等这些方面下功夫。


猜你喜欢

转载自blog.csdn.net/ye15950551288/article/details/80039715