浅析React&Vue两大流行框架优缺点
- vue – 本质是 MVVM 框架,由 MVC 发展而来
- React – 本质是前台组件化框架,不是一个完整的MVC框架,可以认为是MVC中的V(View)
MVVM
MVVM 的出现促进了 GUI 前台开发与后台业务逻辑的分离,极大地提高了前台开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。如下图所示
mvvm1.png
MVVM的设计思想:关注Model的变化,让MVVM框架去自动升级DOM的状态,从而把发者从操作DOM的繁琐步骤中解脱出来!
Bug很难被调试。由于使用双向绑定的模式,当你看到界面异常了,有可能是你View的代码有Bug,也可能是Model的代码有问题。数据绑定使得一个位置的Bug被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。另外,数据绑定的公告是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的。
一个大的板块中model也会很大,尽管使用方便了也很容易保证了数据的一致性,当时长期持有,不释放内存就造成了花费更多的内存。
对于大型的图形应用程序,视图状态较多,ViewModel的构建和维护的成本都会比较高。
yuanli.jpeg
生命周期
Vue生命周期
vue-life.png
React为每个组件提供了生命周期钩子函数去响应不同的时刻,组件的生命周期分为三个部分:(1)实例化;(2)存在期;(3)销毁&清除期。具体周期如下图所示:
React v16.3以前版本
reacct.16.3-down.png
React v16.3以后版本
react-16.3-up.jpeg
数据流管理
Vue组件数据流的问题
而vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的升级对应的虚拟dom。
vue-parent_child.png
React数据是单向不可变的
react是自上而下的单向组件数据流,容器组件&展现组件(也叫傻瓜组s件&聪明组件)是最常用的react组件设计方案,容器组件负责解决复杂的业务逻辑以及数据,展现组件负责解决UI层,通常我们会将展现组件抽出来进行复用或者者组件库的封装,容器组件自身通过state来管理状态,setState升级状态,从而升级UI,通过props将自身的state传递给展现组件实现通信。
这是当业务需求不复杂,页面较简单时我们常用的数据流解决方式,仅用react自身提供的props和state来管理足矣,但是假如略微添加一点复杂度呢,比方当我们项目中遇到这些问题:
state-props.jpg
1,如何实现跨组件通信、状态同步以及状态共享?
react V16.3以前,通过状态提升至最近的共同父组件来实现。(尽管有官方提供的context API,但是旧版本存在一个问题:看似跨组件,实则还是逐级传递,假如中间组件使用了ShouldComponentUpdate检测到当前state和props没有变化,return false,那么context就会无法透传,因而context没有被官方推荐使
react.png
react V16.3版本以后,新版本context处理了之前的问题,可以轻松实现,但仍然存在一个问题,context也是将底部子组件的状态控制交给到了顶级组件,但是顶级组件状态升级的时候肯定会触发所有子组件的re-render,那么也会带来损耗。(尽管我们可以通过少量手段来减少重绘,比方在中间组件的SCU里进行少量判断,但是当项目较大时,我们需要花太多的精力去做这件事)
context.png
2,如何避免组件臃肿?
当某个组件的业务逻辑非常复杂时,我们会发现代码越写越多,由于我们只能在组件内部去控制数据流,没办法抽离,Model和View都放在了View层,整个组件显得臃肿不堪,业务逻辑统统堆在一块,难以维护。
3,如何让状态变得可预知,甚至可回溯?
当数据流混乱时,我们一个执行动作可能会触发一系列的setState,我们如何能够让整个数据流变得可“监控”,甚至可以更细致地去控制每一步数据或者状态的变更?
4,如何解决异步数据流?
react自身并未提供多种解决异步数据流管理的方案,仅用一个setState已经很难满足少量复杂的异步流场景;
组件通信
component-props.png
其实这部分两个比较类似。在Vue 中有三种方式可以实现组件通信:
- 父组件通过props向子组件传递数据或者者回调,尽管可以传递回调,但是我们一般只传数据,只要通过事件的机制来解决
- 子组件向父组件的通信子组件通过事件 向父组件发送消息
- 通过 V2.2.0 中新添加的 provide/inject 来实现父组件向子组件注入数据,可以跨越多个层级。
- 访问
children等不合编码规范的方式。
在React中,组件是如何通信的呢?
- 父组件通过 props 可以向子组件传递数据或者者回调
- 通过 context 进行跨层级的通信,这其实和 provide/inject 起到的作用差不多。
React不支持自己设置事件,Vue中子组件向父组件传递消息有两种方式:事件和回调函数,而且Vue更倾向于使用事件。但是在 React 中我们都是使用回调函数的,这可能是他们二者最大的区别。
模版上不同
- vue – 使用模板(最初由 angular 提出)
- React – 使用 JSX
条件判断
template.png
循环遍历生成
template2.png
JSX
template3.png
总结
- 模板语法上,我更加倾向于 JSX
- 模板分离上,我更加倾向于 vue
补充说明
- JSX 语法(标签、JS 表达式、判断、循环、事件绑定)
- JSX 是语法糖,需被解析成 JS 才能运行
- JSX 是 React 引入的,但不是 React 独有的, 是独立的标准,可被其余项目使用
VDOM
React
React在开发初期就引入虚拟DOM概念,后来发现很好用,但是这是一个无心插柳的结果, 但React的核心思想:组件化,一个Component拯救世界,忘掉烦恼,从此不再操心界面。
为什Virtual Dom快? Javascript很快, Dom很慢 ~
vue:Vue在2.0版本引入了vdom。其vdom是基于snabbdom 库所做的修改。snabbdom是一个开源的vdom库。snabbdom的主要作用就是将传入的JS模拟的DOM结构转换成虚拟的DOM节点。先通过其中的 h函数 将JS模拟的DOM结构转换成虚拟DOM之后,再通过其中的 patch函数 将虚拟DOM转换成真实的DOM渲染到页面中。为了保证页面的最小化渲染,snabbdom引入了Diff算法 ,通过Diff算法找出前后两个虚拟DOM之间的差异,只升级改变了的DOM节点,而不重新渲染为改变的DOM节点。
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <p id="container"></p> <button id="btn-change">change</button> <!-- 引入snabbdom库,先不必纠结为什么这样引入,以及每个文件的作用。 --> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-class.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-props.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-style.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-eventlisteners.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/h.js"></script> <script> //定义patch函数 var patch = snabbdom.init([ snabbdom_class, snabbdom_props, snabbdom_style, snabbdom_eventlisteners ]) //定义h函数 var h = snabbdom.h; //生成一个vnode var vnode = h('ul#list',{},[ h('li.item',{},['Item 1']), h('li.item',{},['Item 2']), ]) console.log(vnode); //获取container var container = document.getElementById('container'); patch(container,vnode);//首次渲染 var btn = document.getElementById('btn-change'); btn.onclick = function() { var newVnode = h('ul#list',{},[ h('li.item',{},['Item 1']), h('li.item',{},['Item B']), h('li.item',{},['Item 3']), ]) patch(vnode,newVnode);//再次渲染 vnode = newVnode;//将修改后的newVnode赋值给vnode } </script> </body></html>
vue中的模板解析和渲染的核心就是:通过相似snabbdom的h()和patch()的函数,先将模板解析成vnode,假如是首次渲染,则通过patch(container,vnode)将vnode渲染至页面,假如是二次渲染,则通过patch(vnode,newVnode),先通过Diff算法比较原vnode和newVnode的差异,以最小的代价重新渲染页面。
组件化的区别
- React 本身就是组件化,没有组件化就不是 React
- vue 也支持组件化,不过是在 MVVM 上的扩展
- 对于组件化,我更加倾向于 React ,做的彻底而清晰
共同点
- 都支持组件化
- 都是数据驱动试图
Chrome 开发工具
React和Vue都有很好的Chrome扩展工具去帮助你找出bug。它们会检查你的应用,让你看到Vue或者者React中的变化。你也可以看到应用中的状态,并实时看到升级。
- React的开发工具: https://www.songma.com/p/06df38a956dc
- Vue的开发工具: https://www.songma.com/p/dab699ca2fd4
DEMO展现
参考文章:
- https://cn.vuejs.org/v2/guide/comparison.html
- https://scotch.io/bar-talk/exciting-new-features-react-163-bye-componentwillreceiveprops-hello-new-context-api
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 浅析React&Vue两大流行框架优缺点