React和Vue的区别
- react数据流是单向的;vue实现数据双向绑定
- react推荐做法是JSX;vue是template
- react只针对MVC中的V; vue是MVVM模式
react如果项目大点,就需要一个状态管理的方案,redux/mbox; vue是渐进式的,想用啥就用啥,想用vuex就用,不用也可以。
重点: react生态丰富,自己组合,效果可控;vue官方提供,省心,定制麻烦。
相同点:都是用虚拟dom、组件化开发。
MVC:controller将model的数据展示在view上 MVVM: 实现view和model自动同步
如何理解vue的变化侦测原理
- vue已经可以数据劫持后,为什么还需要虚拟dom进行diff检测差异?
- 现代前端框架有两种方式侦测变化,一种是pull,一种是push
- pull:其代表是react,react是如何侦测到变化的,我们通常会用setState API显示更新,然后react从一开始就不知道到底是哪里发生了变化,只是知道「有变化了」,然后在进行比较暴力的Diff操作查找「哪里发生了变化」,另外一个代表就是angular的脏检查操作。
- push:vue的响应式系统则是push的代表,当vue程序初始化的时候就会对数据data进行依赖的收集,一旦数据发生变化,响应式系统就会立刻得知,因此vue是一开始就知道「在哪里发生变化了」,但是这又会产生一个问题,如果你熟悉vue的响应式系统就知道,通常绑定一个数据就需要一个watcher,一旦我们的绑定粒度过细就会产生大量的watcher,这会带来内存以及依赖追踪的开销,而粒度过大会无法精准侦测变化,因此vue的设计是选择中等细粒度的方案,在组件级别进行push侦测的方式,也就是那套响应式系统,通常我们会第一时间侦测到发生变化的组件,然后在组件内部进行Virtual DOM Diff获取更加具体的差异,而Virtual DOM Diff则是pull操作, vue是push+pull结合的方式进行侦测的。
- vue中为什么没有类似shouldComponentUpdate?
- react是pul的方式侦测变化,当react知道发生变化后,会使用Virtual DOM Diff进行差异检测,但是很多组件实际上是肯定不会发生变化的,这个时候需要用shouldComponentUpdate进行手动操作来减少diff,从而提高程序整体的性能。
- vue是pull+push的方式侦测变化的,在一开始就知道那个组件发生了变化,因此在push阶段并不需要手动控制diff,而组件内部采用的diff方式实际上是可以引入类似于shouldComponetUpdate相关生命周期的,但是通常合理大小的组件不会有过量的diff,手动优化的价值有限,因此目前vue并没有考虑引入shouldComponentUpdate这种手动优化的生命周期。
vue源码理解
- observer 数据劫持 数据变更通知dep
- dep 被观察者(发布者)
- watcher 观察者(订阅者)
- compiler 编译器解析模版,创建watcher
在数据劫持时给每个属性创建一个dep,在编译的时创建watcher,注册给dep
一个data对应一个observer,每个属性对应一个dep,一个dep可以对应多个watcher,watcher对应一个dom节点
实现一个Vue的类
- 实现一个Observer,对数据进行劫持,通知数据的变化(将使用的要点为:Object.defineProperty()方法)
- 实现一个Compile,对指令进行解析,初始化视图,并且订阅数据的变更,绑定好更新函数ComplieUtil解析指令的公共方法
- 实现一个Watcher,将其作为以上两者的一个中介点,在接收数据变更的同时,让Dep添加当前Watcher,并及时通知视图进行update
- 实现一些VUE的其他功能(Computed、menthods)
如何理解vue响应式系统
- 任何一个vue component 都有一个与之对应的 watcher实例
- vue的data上的属性会被添加getter和setter属性
- 当vue component render函数被执行的时候,data上属性会被读,getter会被调用,此时vue会记录此 vue component所依赖的所有data(依赖收集)
- data被改动时,setter会被调用,此时vue会去通知所有依赖 data 的组件去调用他们的render函数进行更新。