1. mvvm是什么
2. Virtual DOM是什么
3. 前端路由时如何跳转的
4. React和Vue之间的区别
## MVVM
MVVM是什么?和MVC区别?
不管是React还是Vue,都不是MVVM框架,只是**借鉴MVVM的思路**。
* view:用户看到的视图
* Model:一般就是本地数据和数据库中的数据
基本上,通过接口从数据库中读取数据,然后将数据经过处理展现到用户看到的视图;还可以从视图读取用户的输入,然后又将用户的输入通过接口写入到数据库中。
**传统MVC架构**:使用**控制器更新模型**,**视图从模型中获取数据去渲染**。当用户有输入时,会通过控制器去更新模型,并且通知视图进行更新。
![](https://box.kancloud.cn/4048402c30780966fa1f0f33e1c0f1c4_252x202.png)
**MVC缺陷**:巨大缺陷,就是**控制器承担的责任太大**了,随着项目愈加复杂,控制器中的代码会**越来越臃肿**,导致**不利于维护**的情况。
**MVVM**:引入ViewModel概念,ViewModel**只关心数据和业务的处理**,**不关心View如何处理数据**,在这种情况下,View和Model都可以独立出来,**任何一方改变了也不一定需要改变另一方**,并且可以将一些可复用的逻辑放在一个ViewModel中,让多个View复用这个ViewModel
![](https://box.kancloud.cn/430cb79884bf019b1c66e71c9487bf63_454x187.png)
在MVVM中还引入了一个隐式的Binder层,实现了View和ViewModel的绑定
![](https://box.kancloud.cn/2b718d485e492d489c1f308ee70139cc_529x178.png)
**Vue框架**:**ViewModel就是组件的实例**。**View就是模板**,**Model的话在引入Vuex的情况下完全可以和组件分离的**。隐式的**Binder层就是Vue通过解析模板中的差值和指令**,从而实现View和ViewModel的绑定
**MVVM的精髓**:最终要的并不是通过双向绑定或者其他的方式将View与ViewModel绑定起来,而是通过**ViewModel将视图中的状态和用户的行为分离出一个抽象**,这才是MVVM的精髓。
## Virtual DOM
**什么是Virtual DOM?为什么Virtual DOM比原生DOM快?**
操作DOM慢:
因为DOM是属于**渲染引擎**中东西,而JS又是**JS引擎**中的东西,当我们通过JS操作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]
~~~
实际的算法中,如何去识别和改动的哪个节点呢?这就**引入了key这个属性**。
**key属性**:用来给每一个节点打标志的,用于判断是否是同一个节点
当然在判断差异的过程中,还需要**判断节点的属性是否有变化**等。
判断出以上差异,就可以把这些差异记录下来。当对比完两棵树以后,就可以**通过差异去局部更新DOM,实现性能的最优化**。
Virtual Dom的优势:
1. **提高性能**
2. 将Virtual DOM作为一个兼容层,让我们还能对接非Web端的系统,实现跨端开发(ReactNative)。
3. 同样的,通过Virtual DOM我们可以渲染到其他的平台,比如实现SSR,同构渲染等。
4. **实现组件的高度抽象化**。
## 路由原理
**前端路由原理?两种实现方式区别?**
简单,本质是**监听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) 中的stateObj
console.log(e.state)
})
~~~
### 两种模式对比
1. Hash模式只可以更改**#后面的内容**,History模式可以**通过API设置任意的同源URL**。
2. History模式可以通过API添加任**意类型的数据**到历史记录中,**Hash模式只能更改哈希值**,也就是字符串
3. **Hash模式无需后端配置,并且兼容性好**。Histroy模式在用户手动输入地址或者刷新页面的时候会发起URL请求,**后端需要配置index.html页面用于匹配不到静态资源**的时候
## Vue和React之间的区别
1. **表单**:Vue的表单可以使用v-model支持双向绑定,相比于React来说开发商更加方便。
(v-model其实是个语法糖,本质和React写表单的方式没什么区别)
2. **改变数据**:Vue修改状态相比来说要简单很多,React需要使用setState来改变状态,并且使用这个API有一些坑点。并且Vue的底层使用了**依赖追踪**,**页面更新渲染**已经是最优的了,但是React还需要**用户手动去优化**这方面问题。
3. React 16以后,有些钩子函数会执行多次,这是引入Fiber的原因。
4. React需要使用**JSX**,有一定的上手成本,并且需要一整套的工具链支持,但是**完全通过JS来控制页面,更加的灵活**。**Vue使用了模板语法**,相比于JSX来说没有那么灵活,但完全可以**脱离工具链**,通过**直接编写render函数就能在浏览器中运行**。
5. 生态上没有多大差距,React的用户远远高于Vue
6. 上手成本:Vue一开始的定位就是尽可能的降低前端开发的门槛,然而React更多的是改变用户去接收它的概念和思想,相较于Vue来说上手成本略高。
7. React和Vue虽是两个不同的框架,但他们的底层原理都是很相似的。
- 空白目录
- 双樾
- JS基础知识
- JS-WEB-API
- 开发环境
- 运行环境
- ES6
- 原型
- 异步
- 虚拟dom
- mvvm
- 组件化和React
- hybrid
- 其他
- 补充
- 技巧
- 快乐动起来呀
- css
- 掘金小册子
- js基础知识
- ES6知识点
- JS异步
- JS进阶知识
- 思考题
- DevTools Tips
- 浏览器基础知识
- 浏览器缓存机制0
- 浏览器渲染原理
- 安全防范知识点0
- 从V8中看JS性能优化0
- 性能优化琐碎事
- Webpack性能优化0
- 实现小型打包工具0
- React和Vue
- Vue生命周期
- vue基础知识点
- Vue响应式
- vue高级
- React基础
- Vue.js技术解密
- 准备工作
- 数据驱动
- new Vue()
- vue实例挂载
- 组件化
- 深入响应式原理
- 编译
- 扩展
- Vue Router
- Vuex