很多的环节我们了解知道就可以了,正在我们用到的钩子就这么几个
new Vue()
一切的开端
Init Events & Lifecycle(初始化事件与生命周期)(环节)
这个里面制定了一些规则,比如:
初始化:生命周期、事件,但是数据代理还没有开始。
生命周期函数到底有一个,都叫什么名,什么时候去调它们?
事件:事件修饰符(之一once
),得指定规则,以后遇到像是.once的修饰符我得怎么去处理这个事件,都得在这做好
但是数据代理还没有开始: 也就是说在这个环节你new Vue
时候传入的那个data:{n:1}
vm还没有收到,它(vm
)身上还没有_data
这个环节之后它帮你调了beforeCreate
(这是我们第一个生命周期函数)
beforeCreate(生命周期函数)
此时: 无法 通过vm访问到data种的数据、methods的方法。
在数据监测、数据代理之前
经过初始化事件与生命周期环节
我们得知vm身上还没有_data
验证:
1.首先验证它有没有执行
beforeCreate() {
console.log('beforeCreate')
},
beforeCreate
2.输出一下vm
,用debugger
卡一个断点;这样可以分析到哪代码就停到哪
beforeCreate() {
console.log('beforeCreate')
console.log(this)
debugger;
},
Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$attrs: (...)
$children: []
$createElement: ƒ (a, b, c, d)
$listeners: (...)
$options: {components: {…}, directives: {…}, filters: {…}, el: '#root', _base: ƒ, …}
$parent: undefined
$refs: {}
$root: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$scopedSlots: {}
$slots: {}
$vnode: undefined
_c: ƒ (a, b, c, d)
_directInactive: false
_events: {}
_hasHookEvent: false
_inactive: null
_isBeingDestroyed: false
_isDestroyed: false
_isMounted: false
_isVue: true
_renderProxy: Proxy {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_self: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_staticTrees: null
_uid: 0
_vnode: null
_watcher: null
$data: (...)
$isServer: (...)
$props: (...)
$ssrContext: (...)
get $attrs: ƒ reactiveGetter()
set $attrs: ƒ reactiveSetter(newVal)
get $listeners: ƒ reactiveGetter()
set $listeners: ƒ reactiveSetter(newVal)
[[Prototype]]: Object
它身上有下划线data吗(_data
)?没有。
你所传的data
Vue实例对象根本还没收到,而且vm身上没有vm.n
有那method add()
方法吗?没有。
而且很多东西都是null
和undefined
Init injections & reactivity(环节)
初始化:数据监测、数据代理。
也在初始化初始化最重要的
数据监视
和数据代理
也就是说之前Vue是如何监测数据变化的,如何监测数组变化的,给对象里的属性匹配get、set方法的,对数组的那些方法进行二次包装
一旦完成了就调用created
created(生命周期函数)
此时: 可以通过vm访问到data种的数据、methods的配置方法。
在数据监测、数据代理之后
验证:
1.先看一下有没有输出,顺序对不对
created() {
console.log('created')
},
beforeCreate
created
2.查看vm
created() {
console.log('created')
console.log(this)
debugger;
},
Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$attrs: (...)
$children: []
$createElement: ƒ (a, b, c, d)
$listeners: (...)
$options: {components: {…}, directives: {…}, filters: {…}, el: '#root', _base: ƒ, …}
$parent: undefined
$refs: {}
$root: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$scopedSlots: {}
$slots: {}
$vnode: undefined
add: ƒ ()
n: (...)
_c: ƒ (a, b, c, d)
_data: {__ob__: Observer}
_directInactive: false
_events: {}
_hasHookEvent: false
_inactive: null
_isBeingDestroyed: false
_isDestroyed: false
_isMounted: false
_isVue: true
_renderProxy: Proxy {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_self: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_staticTrees: null
_uid: 0
_vnode: null
_watcher: null
_watchers: []
$data: (...)
$isServer: (...)
$props: (...)
$ssrContext: (...)
get $attrs: ƒ reactiveGetter()
set $attrs: ƒ reactiveSetter(newVal)
get $listeners: ƒ reactiveGetter()
set $listeners: ƒ reactiveSetter(newVal)
get n: ƒ proxyGetter()
set n: ƒ proxySetter(val)
[[Prototype]]: Object
这个时候的Vue有了add()方法
,有了n
,有了_data
,并且n的get、set方法都出现了
Has “el” option?
首先它问一个事:有没有el配置项
也就是你new Vue
的时候有没有传el
配置项
传了走
YES
路线到has "template" option?
没有传走NO
路线到when vm.$mount(el) is called
when vm.$mount(el) is called
when:等你
vm.$mount(el) is called:去调用mount(el)
new Vue({
data:{}
})
没有el
写el的时候:
beforeCreate
created
beforeMount
mounted
没写el的时候,也没有写vm.$mount(el)
:
beforeCreate
created
如果没写el但在外面写了vm.$mount(el)
const vm = new Vue({...})
vm.$mount('#root')
beforeCreate
created
beforeMount
mounted
has “template” option?
有没有template
选项;<template>
是标签
有就走
YES
路线到Compile template into render function *
没有就走NO
路线到Compile el's outerHTML as template *
Compile el’s outerHTML as template *
Compile el's :编译el的
outerHTML:外部的HTML(指的是<div id="root"><h2>当前n的值是:{{n}}</h2><button @click="add">点我n+1</button></div>)整个div是模板
as template:就作为模板
验证:
<div id="root" :x="n">
<h2>当前n的值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
如果div不算是模板,那么最终出现的:x="n"
不会解析,如果div也算作是模板,那你能看到的是x=1
<div id="root" x="1">
也就是整个div都算作是模板
Has “el” option? has “template” option? Compile el’s outerHTML as template *
此阶段Vue开始解析模板,生成虚拟DOM(内存中),页面还不能显示解析好的内容
开始解析模板:就是插值语法,@click,什么计算属性都开始解析了
<div id="root" :x="n">
<h2>当前n的值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
这就是没有解析好的模板
Compile template into render function *
容器(<div id="root"></div>
)里面我可以什么都不写
如果你不用换行''
字符串就够了,但是你想要换行写那就要得用到ES6
里面的模板字符串
(``)
template: `
<h2>当前n的值是:{{n}}</h2>
<button @click="add">点我n+1</button>
`,
写了这个你可以不用在容器里面写东西了,它的工作流程就拿这个template
去当模板了,直接解析啊,生成真实DOM啊,最终还是帮你放到容器里面了
结果一看浏览器控制台
[Vue warn]: Error compiling template:
模板编译失败,原因是one root element.
(一个根元素),他的意思就是说如果你想用template
配置项,那么就意味着你不能有俩个根节点(一个是<h2></h2>
另一个是<button></button>
),在它们外面包一个<div></div>
template: `
<div>
<h2>当前n的值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
`,
如果直接把模板写在容器里
有root有绑定事件
x="1"
如果靠template
效果是一样的,但是上面的id=root
和绑定事件x
没了就是把template里的直接替换了容器中的div
这种方式到组件(组件的开始非单文件组件)
里面有个render函
专门做渲染的
这时虚拟DOM已经出现
下面有一个beforeMount
beforeMount(生命周期函数)
将要挂载
或者说是挂载之前
此时:
1.页面呈现的是未经Vue编译
的DOM结构。
2.所有对DOM的操作,最终都不奏效。
验证:
beforeMount() {
console.log('beforeMount')
console.log(this)
debugger;
},
beforeMount
Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$attrs: (...)
$children: []
$createElement: ƒ (a, b, c, d)
$el: div#root
$listeners: (...)
$options: {components: {…}, directives: {…}, filters: {…}, el: '#root', _base: ƒ, …}
$parent: undefined
$refs: {}
$root: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$scopedSlots: {}
$slots: {}
$vnode: undefined
add: ƒ ()
n: (...)
_c: ƒ (a, b, c, d)
_data: {__ob__: Observer}
_directInactive: false
_events: {}
_hasHookEvent: false
_inactive: null
_isBeingDestroyed: false
_isDestroyed: false
_isMounted: false
_isVue: true
_renderProxy: Proxy {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_self: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_staticTrees: null
_uid: 0
_vnode: null
_watcher: null
_watchers: []
$data: (...)
$isServer: (...)
$props: (...)
$ssrContext: (...)
get $attrs: ƒ reactiveGetter()
set $attrs: ƒ reactiveSetter(newVal)
get $listeners: ƒ reactiveGetter()
set $listeners: ƒ reactiveSetter(newVal)
get n: ƒ proxyGetter()
set n: ƒ proxySetter(val)
[[Prototype]]: Object
看页面n没有解析
<div id="root" :x="n">
<h2>当前n的值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
实际上Vue
已经解析完了,但是没来得及往页面上放
2.所有对DOM的操作,最终都不奏效。
在控制台输出原生DOM
> document.querySelector('h2').innerText = "哈哈"
< '哈哈'
页面改变
但是你一点放行debugger
,最终还是当前n的值是:1
(这个是最终把)
因为人家紧随其后执行了Create vm.$el and replace "el" with it
,你无论怎么改DOMCreate vm.$el and replace "el" with it
就还是把之前步骤生成的虚拟DOM
拿过来,直接生成真实DOM,一下子就往vm.$el
上存一份,随后就插入页面了
下一步来到了Create vm.$el and replace "el" with it
Create vm.$el and replace “el” with it
将内存中的虚拟DOM转为真实DOM插入页面
创建一个vm身上的$el
选项,然后替换掉整个el
就在这一步Vue把刚才的虚拟DOM就转成了真实DOM之后,它往vm.$el身上存了一份
随后进入了mounted
mounted(生命周期函数)
挂载完毕
此时:
1.页面中呈现的是经过Vue编译
的DOM。
2.对DOM的操作均有效(尽可能避免)。至此初始化过程结束,一般在此进行:开启定时器、发送网络请求、订阅消息、绑定自定义事件、等初始化操作
。
验证:
mounted(){
console.log('mounted')
console.log(this)
debugger;
}
mounted
Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$attrs: (...)
$children: []
$createElement: ƒ (a, b, c, d)
$el: div#root
$listeners: (...)
$options: {components: {…}, directives: {…}, filters: {…}, el: '#root', _base: ƒ, …}
$parent: undefined
$refs: {}
$root: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
$scopedSlots: {}
$slots: {}
$vnode: undefined
add: ƒ ()
n: (...)
_c: ƒ (a, b, c, d)
_data: {__ob__: Observer}
_directInactive: false
_events: {}
_hasHookEvent: false
_inactive: null
_isBeingDestroyed: false
_isDestroyed: false
_isMounted: true
_isVue: true
_renderProxy: Proxy {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_self: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_staticTrees: null
_uid: 0
_vnode: VNode {tag: 'div', data: {…}, children: Array(3), text: undefined, elm: div#root, …}
_watcher: Watcher {vm: Vue, deep: false, user: false, lazy: false, sync: false, …}
_watchers: [Watcher]
$data: (...)
$isServer: (...)
$props: (...)
$ssrContext: (...)
get $attrs: ƒ reactiveGetter()
set $attrs: ƒ reactiveSetter(newVal)
get $listeners: ƒ reactiveGetter()
set $listeners: ƒ reactiveSetter(newVal)
get n: ƒ proxyGetter()
set n: ƒ proxySetter(val)
[[Prototype]]: Object
页面当的页面n的值是1了而且开发者工具里的html也全解析完了