Web前端之路前端开发前端开发

浅析React&Vue两大流行框架优缺点

2019-04-27  本文已影响12人  pansly

MVVM

MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。如下图所示

mvvm1.png

MVVM的设计思想:关注Model的变化,让MVVM框架去自动更新DOM的状态,从而把发者从操作DOM的繁琐步骤中解脱出来!

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 中有三种方式可以实现组件通信:

在React中,组件是如何通信的呢?

React不支持自定义事件,Vue中子组件向父组件传递消息有两种方式:事件和回调函数,而且Vue更倾向于使用事件。但是在 React 中我们都是使用回调函数的,这可能是他们二者最大的区别。

模版上不同

条件判断

template.png

循环遍历生成

template2.png

JSX

template3.png

总结

补充说明

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的差异,以最小的代价重新渲染页面。

组件化的区别

共同点

Chrome 开发工具

React和Vue都有很好的Chrome扩展工具去帮助你找出bug。它们会检查你的应用,让你看到Vue或者React中的变化。你也可以看到应用中的状态,并实时看到更新。

DEMO展示

参考文章:

上一篇 下一篇

猜你喜欢

热点阅读