- mvvm
MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。 - 响应式数据原理
- 响应式对象
响应式对象,核心就是利用 Object.defineProperty 给数据递归添加了 getter 和 setter,目的就是为了在我们访问数据以及写数据的时候能自动执行一些逻辑:getter 做的事情是依赖收集,setter 做的事情是派发更新。本质上是发布订阅模式(观察者模式)。 - 依赖收集
在组件初始化过程中,会触发所有数据的get,在getter函数中,触发dep.depend做依赖收集,当数据发生变化时,在set函数中进行dep.notify进行变更发布 - 派发更新
实际上就是当数据发生变化的时候,触发 setter 逻辑,把在依赖过程中订阅的的所有观察者,也就是 watcher,都触发它们的 update 过程,这个过程又利用了队列做了进一步优化,在 nextTick 后执行所有 watcher 的 run,最后执行它们的回调函数。
通过setter来触发变量的更新,这里引入了一个队列的概念,这也是 Vue 在做派发更新的时候的一个优化的点,它并不会每次数据改变都触发更新,而是先添加到一个队列里,然后在 nextTick 后执行更新,可以理解为等一段时间一起更新。
队列排序 queue.sort((a, b) => a.id - b.id) 对队列做了从小到大的排序,这么做主要有以下要确保以下几点:
组件的更新由父到子;因为父组件的创建过程是先于子的,所以 watcher 的创建也是先父后子,执行顺序也应该保持先父后子。
用户的自定义 watcher 要优先于渲染 watcher 执行;因为用户自定义 watcher 是在渲染 watcher 之前创建的。
如果一个组件在父组件的 watcher 执行期间被销毁,那么它对应的 watcher 执行都可以被跳过,所以父组件的 watcher 应该先执行。
vue3.0采用es6中的proxy代替Object.defineProperty做数据监听。
- nextTick
此方法可以在数据修改触发dom更新完成之后调用。 在浏览器环境中,常见的 macro task 有 setTimeout、MessageChannel、postMessage、setImmediate;常见的 micro task 有 MutationObsever 和 Promise.then。 - vue生命周期
vue有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载DOM-> 渲染、更新>渲染、卸载等一系列过程
beforeCreate: 组件创建前,组件的属性(data,props,methods等)生效之前
created: 创建组件后。属性已经绑定,但真实dom还没有生成。。$el不可用
beforeMount: 挂载前, render函数首次调用
mounted: 挂载后, $el可用
beforeUpdate: 组件数据更新之前,发生在虚拟dom打补丁之前
update: 组件数据更新后
activated & deactivated: 调用在keep-alive激活后和即将离开激活后
- 父子组件创建挂载执行顺序
父beforeCreate ➜ 父create ➜ 父beforeMount ➜ 子beforeCreate ➜ 子created ➜ 子mounted ➜ 父mounted - 更新
父beforeUpdate ➜ 子beforeUpdate ➜ 子updated ➜ 父updated - 销毁
父beforeDestroy ➜ 子beforeDestroy ➜ 子destroyed ➜ 父destroyed