Vue2.0 Vue生命周期 挂载的流程

Vue官网_生命周期图示

很多的环节我们了解知道就可以了,正在我们用到的钩子就这么几个

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)?没有。
你所传的dataVue实例对象根本还没收到,而且vm身上没有vm.n

有那method add()方法吗?没有。
而且很多东西都是nullundefined

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也全解析完了

这就是整个挂载的流程了

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

结城明日奈是我老婆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值