实例化vue发生了什么?(详解vue生命周期)

实例化vue发生了什么?(详解vue生命周期)

本文将对vue的生命周期进行详细的讲解,让你了解一个vue实例的诞生都经历了什么~

我在Github上创建了一个存放vue笔记的仓库,之后会陆续更新一些知识和项目中遇到的坑,有兴趣的同窗能够去看看哈(欢迎star)! vue

传送门node

实例化一个Vue

const app = new Vue({
  el:"#app',
  data:{
    message:'hello,lifePeriod'
  },
  methods:{
    init(){
      console.log('这是一个方法!')
    }
  }
})

1.触发 beforeCreate 钩子函数

组件实例刚被建立,此时没法访问到 el 属性和 data 属性等..git

beforeCreate(){

    console.log(`元素:${this.$el}`)   //undefined

    console.log(`属性message:${this.message}`) //undefined

    console.log(`方法init:${this.init}`)   //undefined
}

2.对data进行双向绑定,初始化方法(Observer Data && init events)

当一个 vue 实例被建立时,他向 Vue 的响应式系统中加入了其 data 对象中能找到的全部属性.github

利用 es5 特性 Object.defineProperty,遍历 data 对象下全部属性,将其转化为 getter/setter,以便拦截对象赋值与取值操做,而后利用发布/订阅者模式,从而实现数据的双向绑定!web

因此只有当实例被建立时 data 中存在的属性才是响应式的!!!!算法

将methods 下的全部方法进行声明.app

将methods下的方法和data下的属性经过遍历和利用 es5 特性 Object.defineProperty代理到实例下.dom

this.a = this.$data.a = this.data.a;

this.fn = this.$methods.fn = this.methods.fn;

3.触发 created 钩子函数

组件实例建立完成,属性已绑定,但 DOM 还未生成,$el 属性还不存在!函数

created(){

    console.log(`元素:${this.$el}`)   //undefined

    console.log(`属性message:${this.message}`) //message:hey,vue-lifePeriod!

    console.log(`方法init:${this.init}`)   //function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}
}

4.将模板编译成函数 (compile template into render function)

将模板 template 编译成 AST 树、render 函数(new Watch 将模板与数据创建联系)以及 staticRenderFns 函数(经过 diff 算法优化 dom 更新);
运行 render 方法,返回一个 vnode 对象(virtual dom)优化

5. 触发 beforeMount 钩子函数

模板编译/挂载以前

beforeMount(){

    console.log(`元素:${(this.$el)}`)

    console.log(this.$el)  //<div id="app">{{message}}</div> ,咱们发现此时的el还未对数据进行渲染.(虚拟dom的内容)

}

6. 触发 mounted 钩子函数

模板编译/挂载以后

mounted(){

  console.log(`元素:${(this.$el)}`)

  console.log(this.$el)   //<div id="app">{{hello,vue-lifePeriod!}}</div>   ,已将数据渲染到真实dom

}

咱们这时将 app.message 改变为'hey,vue-lifePeriod';

7.触发 beforeUpdate 钩子函数

组件更新以前

beforeUpdate(){

    console.log(this.$el.innerHTML);  //hello,vue-lifePeriod   ,此时,元素的真实dom内容还未改变.

}

8.从新渲染虚拟 dom,并经过 diff 算法对比 vnode 节点差别更新真实 dom (virtual DOM re-render and patch)

9.触发 updated 钩子函数

组件更新以后

updated(){

  console.log(this.$el.innerHTML);  //hey,vue-lifePeriod   ,此时,元素的真实dom内容已经改变.

}

咱们这时调用 app.$destroy()函数对组件进行销毁

10.触发 beforeDestroy 钩子函数

组件销毁以前

beforeDestroy(){

    console.log(this.$el)   //<div id="app">{{hey,vue-lifePeriod!}}</div>

    console.log(`属性message:${this.message}`) //message:hey,vue-lifePeriod!

    console.log(`方法init:${this.init}`)   //function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}

}

11. 销毁数据监听,子组件和解除事件监听!

12. 触发 destroyed钩子函数

组件销毁以后

destroyed(){

    console.log(this.$el)   //<div id="app">{{hey,vue-lifePeriod!}}</div>

    console.log(`属性message:${this.message}`) //message:hey,vue-lifePeriod!

    console.log(`方法init:${this.init}`)   //function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}
}

实例销毁后虽然 dom 和属性方法都还存在,但改变他们都将再也不生效!

app.message = 'hu,vue-lifePeriod';

console.log(app.message) //hey,vue-lifePeriod

相关文章
相关标签/搜索