欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue.js 生命周期

程序员文章站 2022-07-01 19:32:38
...
创建一个Vue实例
每个Vue应用都是通过用Vue函数创建一个新的Vue实例开始的:

var vm = new Vue({
  // 选项
})

虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例

当创建一个 Vue 实例时,你可以传入一个选项对象

一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。一个 todo 应用的组件树可以是这样的:

根实例
└─ TodoList
   ├─ TodoItem
   │  ├─ DeleteTodoButton
   │  └─ EditTodoButton
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics
数据与方法
当一个Vue实例被创建时,它将data对象中的所有的属性加入到Vue的响应式系统中 当这些属性的值发生改变时,视图将会产生"响应",即匹配更新为新的值

// 数据对象
var data = { a: 2 }

// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
  data: data
})

// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true

// 设置属性也会影响到原始数据
vm.a = 3
data.a // => 4
//返回数据
data.a = 4
vm.a // => 4
当这些数据改变时,视图会进行重渲染。只有当实例被创建时data中存在的属性才是响应式的 也就是说添加一个新的属性,比如:

vm.b = 'vue'
那么对b的改动将不会触发任何视图的更新,在晚些时候需要一个属性 但是一开始它为空或不存在,仅需要设置一些初始值。比如:

data: {
  newTodoText: '',
  visitCount: 0,
  hideCompletedTodos: false,
  todos: [],
  error: null
}
生命周期图示
下图展示了实例的生命周期

Vue实例有一个完整的生命周期,从开始创建、初始化数据、挂载虚拟dom、渲染→更新→销毁等一系列过程,这是Vue的生命周期,
Vue实例从 创建到销毁的过程,就是生命周期
每个组件都会经历一个完整的生命周期,分为三个阶段:初始化、运行中、销毁
1.组件通过new Vue()创建出来之后会初始化事件和生命周期,执行beforeCreate钩子函数,数据还没挂载,无法访问到数据,一般不做操作
2.挂载数据、捆绑事件等,执行created函数,使用到数据或者更改数据,不会触发updated函数,渲染前倒数第二次更改数据,不会触发其他的钩子函数,一般做初始数据的获取
3.编译模板把虚拟dom放入到render函数中渲染,执行beforeMount钩子函数,虚拟dom已经创建完成,可以更改数据,不会触发updated,渲染前更改数据的机会,不会触发其他的钩子函数,一般做初始数据的获取
4.开始render,渲染虚拟dom,执行mounted钩子函数,组件已经出现在页面中,数据、dom都已经处理好了,事件都已经挂载好了,可以操作虚拟dom
5.当组件或虚拟dom的数据更改之后,会立即执行beforeUpdate,然后vue的dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染
6.当更新完成后,执行updated,数据已经更改完成,虚拟dom也重新render完成,可以操作更新后的虚拟dom
7.当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些其他事件,例如清除计时器、清除非指令绑定的事件等
8.组件的数据绑定、监听...去掉后只剩下虚拟dom空壳,执行destroyed,一般在这里做一些其他事件

Vue.js 生命周期

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <script src="vue.min.js"></script>

</head>
<body>
<div id="app">
   <test></test>    
</div>
<template id="test">
    <div>
    <p class="list">组件</p>
    <button @click="destroy">destroy</button>
    <input type="text" v-model="test">
    <p>test:{{test}}</p>
    </div>
</template>
</body>
<script>
    Vue.component("test",{
        template:"#test",
        data:function(){
            return {test:'hello vue'}
        },
        timer:null,
        methods:{
            destroy:function(){
                this.$destroy()
            }
        },
        beforeCreate:function(){
            console.log('new vue() 数据没挂载')
            console.log(this.test)
            console.log(document.getElementsByClassName("test")[0])
        },
        created:function(){
            console.log("created已经可以使用数据,更改数据不会触发update函数")
            this.test+='——'
            console.log('渲染倒数第二次更改数据,不触发其他的钩子函数,做初始化数据的获取')
            console.log('编译模板将虚拟dom放入rende函数中准备渲染')
        },
        beforeMount:function(){
                console.log('beforeMount:虚拟dom创建完成,更改数据不会触发update')
                this.test+='极客教程'
                console.log(document.getElementsByClassName("test")[0])
                console.log('开始render,渲染虚拟dom')
        },
        mounted:function(){
                console.log('组件出现在页面,数据、虚拟dom处理完毕,事件完成挂载')
                console.log(document.getElementsByClassName("test")[0])
                console.log('操作虚拟dom')
        },
        beforeUpdate:function(){
            //这里不能更改数据,否则陷入死循环
            console.log('beforeUpdate:重新渲染之前触发')
            console.log('vue的虚拟dom机制重新构建虚拟dom与上次的虚拟dom利用diff算法进行对比之后重新渲染')
        },
        updated:function(){
            //这里不能更改数据,否则陷入死循环
            console.log('updated:数据更改,重新render完成')
        },
        beforeDestroy:function(){
            console.log('beforeDestroy:销毁前执行($test方法被调用的时候会执行),清除计时器、清除非指令绑定的事件等')
        },
        destroyed:function(){
            console.log('destroyed:组件的数据绑定、监听')
        }
    })
    new Vue({
    }).$mount('#app')
</script>

生命周期钩子    详细

beforeCreate    在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用

created    实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见

beforeMount    在挂载开始之前被调用:相关的 render 函数首次被调用

mounted    el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内

beforeUpdate    数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程

updated    由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作

activated    keep-alive 组件**时调用

deactivated    keep-alive 组件停用时调用

beforeDestroy    实例销毁之前调用。在这一步,实例仍然完全可用

destroyed    Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁