前端框架学习总结之Angular、React与Vue的比较详解
近几年前端的技术发展很快,细分下来,主要可以分成四个方面:
1.开发语言技术,主要是es6&7,coffeescript,typescript等;
2.开发框架,如angular,react,vue.js,angular2等;
3.开发工具的丰富和前端工程化,像grunt,gulp,webpack,npm,eslint,mocha这些技术;
4.前端开发范围的扩展,如服务端的nodejs,express,koa,meteor,graphql;移动端和跨平台的phonegap,ionic,reactnative,weex;计算机图形学和3维建模领域的webgl(three.js等);可视化与数据分析领域的d3.js等;包括浏览器不断开放的更多新特性和接口比如svg,canvas,蓝牙,电池,本地存储,service worker,houdini等新的api能力,以及像wasm这样的底层优化技术;
就开发框架这块,angular(1&2),react,vue目前占据着主流地位而且会相持比较长的一段时间,所以这里对比一下这三门技术,以便之后的技术选型。
一、数据流
数据绑定
angular 使用双向绑定即:界面的操作能实时反映到数据,数据的变更能实时展现到界面。
实现原理:
$scope变量中使用脏值检查来实现。像ember.js是基于setter,getter的观测机制,
$scope.$watch
函数,监视一个变量的变化。函数有三参数,”要观察什么”,”在变化时要发生什么”,以及你要监视的是一个变量还是一个对象。
使用ng-model时,你可以使用双向数据绑定。
使用$scope.$watch
(视图到模型)以及$scope.$apply
(模型到视图),还有$scope.$digest
调用$scope.$watch
时只为它传递了一个参数,无论作用域中的什么东西发生了变化,这个函数都会被调用。在ng-model中,这个函数被用来检查模型和视图有没有同步,如果没有同步,它将会使用新值来更新模型数据。
双向绑定的三个重要方法:
$scope.$apply() $scope.$digest() $scope.$watch()
在angularjs双向绑定中,有2个很重要的概念叫做dirty check,digest loop,dirty check(脏检测)是用来检查绑定的scope中的对象的状态的,例如,在js里创建了一个对象,并且把这个对象绑定在scope下,这样这个对象就处于digest loop中,loop通过遍历这些对象来发现他们是否改变,如果改变就会调用相应的处理方法来实现双向绑定
vue 也支持双向绑定,默认为单向绑定,数据从父组件单向传给子组件。在大型应用中使用单向绑定让数据流易于理解。
脏检测的利弊
和ember.js等技术的getter/setter观测机制相比(优):
getter/setter当每次对dom产生变更,它都要修改dom树的结构,性能影响大,angular会把批量操作延时到一次更新,性能相对较好。
和vue相比(劣):
vue.js 有更好的性能,并且非常非常容易优化,因为它不使用脏检查。angular,当 watcher 越来越多时会变得越来越慢,因为作用域内的每一次变化,所有 watcher 都要重新计算。并且,如果一些 watcher 触发另一个更新,脏检查循环(digest cycle)可能要运行多次。 angular 用户常常要使用深奥的技术,以解决脏检查循环的问题。有时没有简单的办法来优化有大量 watcher 的作用域。vue.js 则根本没有这个问题,因为它使用基于依赖追踪的观察系统并且异步列队更新,所有的数据变化都是独立地触发,除非它们之间有明确的依赖关系。唯一需要做的优化是在 v-for 上使用 track-by。
react-单向数据流
mvvm流的angular和vue,都是通过类似模板的语法,描述界面状态与数据的绑定关系,然后通过内部转换,把这个结构建立起来,当界面发生变化的时候,按照配置规则去更新相应的数据,然后,再根据配置好的规则去,从数据更新界面状态。
react推崇的是函数式编程和单向数据流:给定原始界面(或数据),施加一个变化,就能推导出另外一个状态(界面或者数据的更新)。
react和vue都可以配合redux来管理状态数据。
二、视图渲染
angular1
angularjs的工作原理是:html模板将会被浏览器解析到dom中, dom结构成为angularjs编译器的输入。angularjs将会遍历dom模板, 来生成相应的ng指令,所有的指令都负责针对view(即html中的ng-model)来设置数据绑定。因此, ng框架是在dom加载完成之后, 才开始起作用的。
react
react 的渲染建立在 virtual dom 上——一种在内存中描述 dom 树状态的数据结构。当状态发生变化时,react 重新渲染 virtual dom,比较计算之后给真实 dom 打补丁。
virtual dom 提供了函数式的方法描述视图,它不使用数据观察机制,每次更新都会重新渲染整个应用,因此从定义上保证了视图与数据的同步。它也开辟了 javascript 同构应用的可能性。
在超大量数据的首屏渲染速度上,react 有一定优势,因为 vue 的渲染机制启动时候要做的工作比较多,而且 react 支持服务端渲染。
react 的 virtual dom 也需要优化。复杂的应用里可以选择 1. 手动添加 shouldcomponentupdate 来避免不需要的 vdom re-render;2. components 尽可能都用 purerendermixin,然后采用 flux 结构 + immutable.js。其实也不是那么简单的。相比之下,vue 由于采用依赖追踪,默认就是优化状态:动了多少数据,就触发多少更新,不多也不少。
react 和 angular 2 都有服务端渲染和原生渲染的功能。
vue.js 不使用 virtual dom 而是使用真实 dom 作为模板,数据绑定到真实节点。vue.js 的应用环境必须提供 dom。vue.js 有时性能会比 react 好**,而且几乎不用手工优化。
三、性能与优化
性能方面,这几个主流框架都应该可以轻松应付大部分常见场景的性能需求,区别在于可优化性和优化对于开发体验的影响。vue 的话需要加好 track-by 。react 需要 shouldcomponentupdate 或者全面 immutable,angular 2 需要手动指定 change detection strategy。从整体趋势上来说,浏览器和手机还会越变越快,框架本身的渲染性能在整个前端性能优化体系中,会渐渐淡化,更多的优化点还是在构建方式、缓存、图片加载、网络链路、http/2 等方面。
四、模块化与组件化
angular1 -> angular2
angular1使用依赖注入来解决模块之间的依赖问题,模块几乎都依赖于注入容器以及其他相关功能。不是异步加载的,根据依赖列出第一次加载所需的所有依赖。
可以配合类似于require.js来实现异步加载,懒加载(按需加载)则是借助于 oclazyload 方式的解决方案,但是理想情况下应该是本地框架会更易懂。
angular2使用es6的module来定义模块,也考虑了动态加载的需求。
vue
vue中指令和组件分得更清晰。指令只封装 dom 操作,而组件代表一个自给自足的独立单元 —— 有自己的视图和数据逻辑**。在 angular1 中两者有不少相混的地方。
react
一个 react 应用就是构建在 react 组件之上的。
组件有两个核心概念:props,state。
一个组件就是通过这两个属性的值在 render 方法里面生成这个组件对应的 html 结构。
传统的 mvc 是将模板放在其他地方,比如 script 标签或者模板文件,再在 js 中通过某种手段引用模板。按这种思路,想想多少次我们面对四处分散的模板片段不知所措?纠结模板引擎,纠结模板存放位置,纠结如何引用模板。
react 认为组件才是王道,而组件是和模板紧密关联的,组件模板和组件逻辑分离让问题复杂化了。所以就有了 jsx 这种语法,就是为了把 html 模板直接嵌入到 js 代码里面,这样就做到了模板和组件关联,但是 js 不支持这种包含 html 的语法,所以需要通过工具将 jsx 编译输出成 js 代码才能使用(可以进行跨平台开发的依据,通过不同的解释器解释成不同平台上运行的代码,由此可以有rn和react开发桌面客户端)。
五、语法与代码风格
react,vue,angular2都支持es6,angular2官方拥抱了typescript这种 javascript 风格。
react 以 javascript 为中心,angular 2 依然保留以 html 为中心。angular 2 将 “js” 嵌入 html。react 将 “html” 嵌入 js。angular 2 沿用了 angular 1 试图让 html 更强大的方式。
react 推荐的做法是 jsx + inline style,也就是把 html 和 css 全都整进 javascript 了。vue 的默认 api 是以简单易上手为目标,但是进阶之后推荐的是使用 webpack + vue-loader 的单文件组件格式(template,script,style写在一个vue文件里作为一个组件)
总结
好了,以上就是这篇文章的全部内容了,本文的话题实际上很大,需要对angular,react和vue三门技术有足够深入的了解,所以难免有很多总结的不全或者不够深入的地方,后续我会不断完善和修改。希望本文的内容对大家的学习或者工作能带来一定的帮助。
上一篇: vue.js 获取当前自定义属性值