分享

React 和 Vue 两⼤框架之间的相爱相杀

 昵称36969213 2022-11-08 发布于安徽

React 和 Vue 应该是国内当下最⽕热的前端框架,当然 Angular 也是⼀个不错的框架,但是这个产品国内使⽤的⼈很少再加上对Angular 也不怎么熟悉,所以框架的章节中不会涉及到 Angular 的
内容。

将会来学习以下⼏个内容

  • MVVM 是什么

  • Virtual DOM 是什么

  • 前端路由是如何跳转的

  • React 和 Vue 之间的区别

MVVM
涉及⾯试题:什么是 MVVM?⽐之 MVC 有什么区别?
⾸先先申明⼀点,不管是 React 还是 Vue,它们都不是 MVVM 框架,只是有借鉴 MVVM 的思路。⽂中拿 Vue 举例也是为了更好地理解 MVVM 的概念。

接下来先说下 View 和 Model:

  • View 很简单,就是⽤户看到的视图

  • Model 同样很简单,⼀般就是本地数据和数据库中的数据

基本上,我们写的产品就是通过接⼝从数据库中读取数据,然后将数据经过处理展现到⽤户看到的视图上。当然我们还可以从视图上读取⽤户的输⼊,然后⼜将⽤户的输⼊通过接⼝写⼊到数据库中。但是,如何将数据展示到视图上,然后⼜如何将⽤户的输⼊写⼊到数据中,不同的⼈就产⽣了不同的看法,从此出现了很多种架构设计。
传统的 MVC 架构通常是使⽤控制器更新模型,视图从模型中获取数据去渲染。当⽤户有输⼊时,会通过控制器去更新模型,并且通知视图进⾏更新。但是 MVC 有⼀个巨⼤的缺陷就是控制器承担的责任太⼤了,随着项⽬愈加复杂,控制器中的代码会越来越臃肿,导致出现不利于维护的情况。

在 MVVM 架构中,引⼊了 ViewModel 的概念。ViewModel 只关⼼数据和业务的处理,不关⼼ View 如何处理数据,在这种情况下,View 和 Model 都可以独⽴出来,任何⼀⽅改变了也不⼀定需要改变另⼀⽅,并且可以将⼀些可复⽤的逻辑放在⼀个 ViewModel 中,让多个 View 复⽤这个 ViewModel。
以 Vue 框架来举例,ViewModel 就是组件的实例。View 就是模板,Model 的话在引⼊ Vuex 的情况下是完全可以和组件分离的。除了以上三个部分,其实在 MVVM 中还引⼊了⼀个隐式的 Binder层,实现了 View 和 ViewModel 的绑定。

同样以 Vue 框架来举例,这个隐式的 Binder 层就是 Vue 通过解析模板中的插值和指令从⽽实现 View 与 ViewModel 的绑定。

对于 MVVM 来说,其实最重要的并不是通过双向绑定或者其他的⽅式将 View 与 ViewModel 绑定起来,⽽是通过 ViewModel 将视图中的状态和⽤户的⾏为分离出⼀个抽象,这才是 MVVM 的精髓。

Virtual DOM涉及⾯试题:什么是 Virtual DOM?为什么 Virtual DOM ⽐原⽣ DOM 快?
⼤家都知道操作 DOM 是很慢的,为什么慢的原因已经在「浏览器渲染原理」章节中说过,这⾥就不再赘述了。那么相较于 DOM 来说,操作 JS 对象会快很多,并且我们也可以通过 JS 来模拟DOM
const ul = {
 tag: 'ul',
  props: {
 class: 'list'
 },
children: {
tag: 'li',
children: '1'
}
}
上述代码对应的 DOM 就是
<ul class='list'>
<li>1</li>
</ul>

那么既然 DOM 可以通过 JS 对象来模拟,反之也可以通过 JS 对象来渲染出对应的 DOM。当然了,通过 JS 来模拟 DOM 并且渲染对应的 DOM 只是第⼀步,难点在于如何判断新旧两个 JS 对象的最⼩差异并且实现局部更新 DOM。

⾸先 DOM 是⼀个多叉树的结构,如果需要完整的对⽐两颗树的差异,那么需要的时间复杂度会是 O(n ^ 3),这个复杂度肯定是不能接受的。于是 React 团队优化了算法,实现了 O(n) 的复杂度来对⽐差异。实现 O(n) 复杂度的关键就是只对⽐同层的节点,⽽不是跨层对⽐,这也是考虑到在实际业务中很少会去跨层的移动 DOM 元素。

所以判断差异的算法就分为了两步

⾸先从上⾄下,从左往右遍历对象,也就是树的深度遍历,这⼀步中会给每个节点添加索引,便于最后渲染差异⼀旦节点有⼦元素,就去判断⼦元素是否有不同在第⼀步算法中我们需要判断新旧节点的 tagName 是否相同,如果不相同的话就代表节点被替换了。如果没有更改 tagName 的话,就需要判断是否有⼦元素,有的话就进⾏第⼆步算法。在第⼆步算法中,我们需要判断原本的列表中是否有节点被移除,在新的列表中需要判断是否有新的节点加⼊,还需要判断节点是否有移动。
举个例⼦来说,假设⻚⾯中只有⼀个列表,我们对列表中的元素进⾏了变更
// 假设这⾥模拟⼀个 ul,其中包含了 5 个 li
[1, 2, 3, 4, 5]
// 这⾥替换上⾯的 li
[1, 2, 5, 4]

从上述例⼦中,我们⼀眼就可以看出先前的 ul 中的第三个 li 被移除了,四五替换了位置。

那么在实际的算法中,我们如何去识别改动的是哪个节点呢?这就引⼊了 key 这个属性,想必⼤家在 Vue 或者 React 的列表中都⽤过这个属性。这个属性是⽤来给每⼀个节点打标志的,⽤于判断是否是同⼀个节点。当然在判断以上差异的过程中,我们还需要判断节点的属性是否有变化等等。

当我们判断出以上的差异后,就可以把这些差异记录下来。当对⽐完两棵树以后,就可以通过差异去局部更新 DOM,实现性能的最优化。

当然了 Virtual DOM 提⾼性能是其中⼀个优势,其实最⼤的优势还是在于:
1. 将 Virtual DOM 作为⼀个兼容层,让我们还能对接⾮ Web 端的系统,实现跨端开发。
2. 同样的,通过 Virtual DOM 我们可以渲染到其他的平台,⽐如实现 SSR、同构渲染等等。
3. 实现组件的⾼度抽象化

路由原理
涉及⾯试题:前端路由原理?两种实现⽅式有什么区别?
前端路由实现起来其实很简单,本质就是监听 URL 的变化,然后匹配路由规则,显示相应的⻚⾯,并且⽆须刷新⻚⾯。⽬前前端使⽤的

路由就只有两种实现⽅式

  • Hash 模式

  • History 模式

  • Hash 模式

www.test.com/#/ 就是 Hash URL,当 # 后⾯的哈希值发⽣变化
时,可以通过 hashchange 事件来监听到 URL 的变化,从⽽进⾏
跳转⻚⾯,并且⽆论哈希值如何变化,服务端接收到的 URL 请求永
远是 www.test.com。
window.addEventListener('hashchange', () => {
// ... 具体逻辑
})
Hash 模式相对来说更简单,并且兼容性也更好。

History 模式
History 模式是 HTML5 新推出的功能,主要使⽤
history.pushState 和 history.replaceState 改变 URL。
通过 History 模式改变 URL 同样不会引起⻚⾯的刷新,只会更新浏览器的历史记录。
// 新增历史记录
history.pushState(stateObject, title, URL)
// 替换当前历史记录
history.replaceState(stateObject, title, URL)
当⽤户做出浏览器动作时,⽐如点击后退按钮时会触发 popState
事件
window.addEventListener('popstate', e => {
// e.state 就是 pushState(stateObject) 中的
stateObject
console.log(e.state)
})

两种模式对⽐
Hash 模式只可以更改 # 后⾯的内容,History 模式可以通过API 设置任意的同源 URL

History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串Hash 模式⽆需后端配置,并且兼容性好。History 模式在⽤户⼿动输⼊地址或者刷新⻚⾯的时候会发起 URL 请求,后端需要配置 index.html ⻚⾯⽤于匹配不到静态资源的时候

Vue 和 React 之间的区别
Vue 的表单可以使⽤ v-model ⽀持双向绑定,相⽐于 React 来说开发上更加⽅便,当然了 v-model 其实就是个语法糖,本质上和React 写表单的⽅式没什么区别。

改变数据⽅式不同,Vue 修改状态相⽐来说要简单许多,React 需要使⽤ setState 来改变状态,并且使⽤这个 API 也有⼀些坑点。并且 Vue 的底层使⽤了依赖追踪,⻚⾯更新渲染已经是最优的了,但是 React 还是需要⽤户⼿动去优化这⽅⾯的问题。

React 16以后,有些钩⼦函数会执⾏多次,这是因为引⼊ Fiber 的原因,这在后续的章节中会讲到。

React 需要使⽤ JSX,有⼀定的上⼿成本,并且需要⼀整套的⼯具链⽀持,但是完全可以通过 JS 来控制⻚⾯,更加的灵活。Vue 使⽤了模板语法,相⽐于 JSX 来说没有那么灵活,但是完全可以脱离⼯具链,通过直接编写 render 函数就能在浏览器中运⾏。

在⽣态上来说,两者其实没多⼤的差距,当然 React 的⽤户是远远⾼于 Vue 的。

在上⼿成本上来说,Vue ⼀开始的定位就是尽可能的降低前端开发的⻔槛,然⽽ React 更多的是去改变⽤户去接受它的概念和思想,相较于 Vue 来说上⼿成本略⾼。

⼩结
这⼀章节中我们学习了⼏⼤框架中的相似点,也对⽐了 React 和Vue 之间的区别。其实我们可以发现,React 和 Vue 虽然是两个不同的框架,但是他们的底层原理都是很相似的,⽆⾮在上层堆砌了⾃⼰的概念上去。所以我们⽆需去对⽐到底哪个框架⽜逼,引⽤尤⼤的⼀句话
说到底,就算你证明了 A ⽐ B ⽜逼,也不意味着你或者你的项⽬就⽜逼了... ⽐起争这个,不如多想想怎么让⾃⼰变得更⽜逼吧。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多