温故而知新之VUE(一)
2018-11-03 本文已影响1人
lmmy123
VUE 是一个构建用户界面的渐进式前端框架
生命周期
生命周期钩子中的this上下文指向它的VUE实例
图示:
- new Vue({}) --- init Events & LifeCycle
- beforeCreate --- init injections & reactivity
- created --- has 'template' options?
yes: compile template into render Function
no: compile el's outerHTML as template
在实例创建完成后调用,$el属性目前不可见 - beforeMount --- create vm.$el and replace 'el' with it
该钩子在服务器端渲染期间不能被调用 - mounted 该钩子在服务器端渲染期间不能被调用
不会承诺所有的子组件都会一起被重绘,如果你希望整个视图都重绘完毕,可以使用vm.$nextTick(function(){})
- beforeDestroy -- 组件销毁之前
- destroyed
- beforeUpdate - Virtual DOM re-render and patch
- updated
- activated --- keep-alive 组件激活时调用
- deactivated ---keep-alive组件停用时调用
- errorCaptured ---2.5.0新增 捕获一个来自子孙组件的错误时被调用
渲染流程
Vue.prototype._init = function(options){
var vm = this
vm._uid = uid$1++; //默认自增
vm._isVue = true;
// merge options
if(options && options._isComponent){
...
}else{
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor), // 获取Vue实例 base options
options || {},
vm
)
}
initProxy(vm) // 初始化 代理 达到的效果 vm._renderProxy = new Proxy(vm,handlers)
vm._self = vm
initLifecycle(vm) // 设置 vm.$parent vm.$root vm.$children vm.$refs 什么的
initEvents(vm) // 初始化vm.events
initRender(vm) // vm._c vm.$createElement
callHook(vm, 'beforeCreate')
initInjections(vm)
initState(vm) // initProps initMethods initData(vm) initData 中 初始化数据并且 new Observer(value) new Observer({msg: 'Hello word'})
// this.dep = new Dep() 生成依赖收集器
// 如果传参是数组,this.observeArray(value)
// 不是 this.walk(value) => 遍历value defineReactive(value,keys[i],value[keys[i]])
//defineReactive 调用 Object.defineProperty()设置数据访问器属性
// get: if(Dep.target){ dep.depend()} 如果有子元素 遍历添加依赖
// set: dep.notify // 发布消息
}
initProvide(vm) //vm._provide
callHook(vm, 'created')
if(vm.$options.el){
vm.$mount(vm.$options.el) // 挂载dom
}
// vm.$mount(vm.$options.el) 这个方法中 判读有没有 'el' ,有没有 ‘template’
// compileToFunctions(template,{...},this) // 编译成函数 返回 { render, staticRenderFns}
// compile 函数 解析成 AST抽象语法树
// render => vnode 在 mountComponent方法 调用了 vnode = render.call(vm._renderProxy, vm.$createElement)
/**vm.$el= el
* callHook(vm, 'beforeMount')
* var updateComponent
* vm._watcher = new Watcher(vm, updateComponent, noop)
* if(vm.$node == null){
vm._isMounted = true;
callHook(vm, 'mounted')
}*/
// vm._update(vm._render(),hydrating)
// vm._render() 返回一个 vnode 使用的是 vm.$createElement 创建的vnode
// 接下来 vnode =》 真实的el节点 通过 vm.$el = vm._patch(prevVnode, vnode)
// compile parse 函数的生成
export const createCompiler = createCompilerCreator(function baseCompile(
template: string,
optionss: CompilerOptions
):CompiledResult{
const ast = parse(template.trim(), options) // 1.parse
optimize(ast, options) // 2.optimize
const code = generate(ast, options) //3.generate
return {
ast,
render: code.render,
staticRenderFns: code.staticRenderFns
}
})
// 1. parse 生成 AST抽象语法树
// 2. optimize 将AST节点进行静态节点标记(static,staticRoot),为后面patch过程对比新旧vnode做优化,标记为static的节点在diff算法中被忽略 使用深度优先遍历算法
// 3.generate 生成render函数
// patch 方法 将vnode生成真实的dom
// vm.$el = vm._patch_(vm.$el,vnode...) 初始化时
// vm.$el = vm._pathc_(prevVnode,vnode) update时