主题
Vue
1. nextTick
在下次 dom
更新循环结束之后执行延迟回调, 可用于获取更新后的 dom
状态
- 新版本中默认是
mincrotasks
,v-on
中会使用macrotasks
macrotasks
任务的实现:setImmediate
/MessageChannel
/setTimeout
2. 生命周期
init
initLifecycle/Event
,往vm
上挂载各种属性callHook: beforeCreated
: 实例刚创建initInjection/initState
: 初始化注⼊和data
响应性created
: 创建完成,属性已经绑定, 但还未生成真实dom
- 进行元素的挂载:
$el
/vm.$mount()
- 是否有
template
: 解析成render function
*.vue
文件:vue-loader
会将<template>
编译成render function
beforeMount
: 模板编译/挂载之前- 执行
render function
,生成真实的dom
, 并替换到dom tree
中 mounted
: 组件已挂载
update
- 执行
diff
算法, 比对改变是否需要触发UI
更新 flushScheduleQueue
watcher.before
: 触发beforeUpdate
钩子 -watcher.run()
: 执行watcher
中的notify
, 通知所有依赖项更新UI
- 触发
updated
钩子: 组件已更新 actived
/deactivated(keep-alive)
: 不销毁, 缓存, 组件激活与失活destroy
beforeDestroy
: 销毁开始- 销毁自身且递归销毁子组件以及事件监听
remove()
: 删除节点watcher.teardown()
: 清空依赖vm.$off()
: 解绑监听
- destroyed : 完成后触发钩子
上面是 vue 的声明周期的简单梳理,接下来我们直接以代码的形式来完成 vue 的初始化
js
new Vue({});
// 初始化Vue实例
function initVue() {
// 挂载属性
initLifeCycle(vm);
// 初始化事件系统,钩子函数等
initEvent(vm);
// 编译slot、vnode
initRender(vm);
// 触发钩子
callHook(vm, "beforeCreate");
// 添加inject功能
initInjection(vm);
// 完成数据响应性 props/data/watch/computed/methods
initState(vm);
// 添加 provide 功能
initProvide(vm);
// 触发钩子
callHook(vm, "created");
// 挂载节点
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
}
// 挂载节点实现
function mountComponent(vm) {
// 获取 render function
if (!this.options.render) {
// template to render
// Vue.compile = compileToFunctions()
let { render } = compileToFunctions();
this.options.render = render;
}
// 触发钩子
callHook("beforeMounte");
// 初始化观察者
// render 渲染 vdom,
vdom = vm.render();
// update: 根据 diff 出的 patchs 挂载成真实的 dom
vm._update(vdom);
// 触发钩子
callHook(vm, "mounted");
}
// 更新节点实现
function queueWatcher(watcher) {
nextTick(flushScheduleQueue);
}
// 清空队列
function flushScheduleQueue() {
// 遍历队列中所有修改
for (let i = 0; i < watcherQueue.length; i++) {
// beforeUpdate
watcher.before();
// 依赖局部更新节点
watcher.update();
callHook("updated");
}
}
// 销毁实例实现
Vue.prototype.$destory = function () {
// 触发钩子
callHook(vm, "beforeDestory");
// 自身及子节点
remove();
// 删除依赖
watcher.teardown();
// 删除监听
vm.$off();
// 触发钩子
callHook(vm, "destoryed");
};
3. Proxy 相比于 defineProperty 的优势
- 数组变化也能监听到
- 不需要深度遍历监听
js
let data = { a: 1 };
let reactiveData = new Proxy(data, {
get: function (target, name) {
// ...
},
// ...
});
4. vue-router
mode
hash
history
跳转
this.$router.push()
<router-link to=""></router-link>
占位
vue
<router-view></router-view>
5. vuex
state
: 状态中心mutations
: 更改状态actions
: 异步更改状态getters
: 获取状态modules
: 将state
分成多个modules
,便于管理