Vue 组件生命周期钩子函数

2019-05-17 admin

所谓生命周期钩子函数(简称生命周期函数),指的是组件的创建更新销毁三个阶段所触发执行的函数。根据每个阶段触发的钩子函数,我们可以相应的做一些操作,如获取后端接口数据、监听事件、执行事件、执行定时器、移除事件、清理定时器等等。

生命周期根据上面的三个阶段,本人总结为:

后续会根据这三大周期,分别说明生命周期函数。

为了方便理解,本人在 http://jsrun.net 上编写了例子。(一个跟 jsfiddle 差不多的网站,国内 jsfiddle 被墙了)

生命周期示意图

首先看下官网的生命周期示意图,这里的生命周期函数都是针对浏览器端的,服务端目前只支持 beforeCreatecreated 这两个生命周期函数。

其中官网并没有把 renderrenderError 函数归纳为生命周期钩子函数。

其中 Has "el" option 对比如下:

有 el

// 有el属性的情况下
new Vue({
  el: "#app",
  beforeCreate: function() {
    console.log("调用了beforeCreate");
  },
  created: function() {
    console.log("调用了created");
  },
  beforeMount: function() {
    console.log("调用了beforeMount");
  },
  mounted: function() {
    console.log("调用了mounted");
  }
});

// 输出结果
// 调用了beforeCreate
// 调用了created
// 调用了beforeMount
// 调用了mounted

无 el

// 有el属性的情况下
const vm new Vue({
  beforeCreate: function() {
    console.log("调用了beforeCreate");
  },
  created: function() {
    console.log("调用了created");
  },
  beforeMount: function() {
    console.log("调用了beforeMount");
  },
  mounted: function() {
    console.log("调用了mounted");
  }
});

// 输出结果
// 调用了beforeCreate
// 调用了created

无 el 时,如果需要挂载,可以这样处理:vm.$mount('#app')。效果一样了,本质上没区别,只是用法更灵活。

实例化期

实例化期会涉及到以下生命周期函数(执行顺序自上而下):

  • beforeCreate
  • created
  • beforeMount
  • mouted

其中 beforeCreatecreated 中间会触发 render 函数,如果有 template 会转换为 render 函数进行渲染。(当然如果组件的 定义了 render 函数,那么 render 函数优先级更高)

详细的例子请看 http://jsrun.net/LZyKp/edit

// 输出请看 右下角 Console 命令行工具
new Vue({
  el: '#dynamic-component-demo',
  data: {
    num: 2,
  },
  beforeCreate(){
    console.log("beforeCreate",this.num,this.a);
    // 输出为 befoerCreate,,
    // this.num 数据还没监测,this.a 方法未绑定
  },
  created(){
    console.log("created",this.num,this.a,this.$el);
    // 输出为 created, 2, function () { [native code] }
  },
  beforeMount(){
    console.log(this.$el.innerText);
    // 输出 {{ num }},还是原来的 DOM 内容
  },
  mounted(){
    console.log(this.$el.innerText);
    // 输出 2,已经是 vue 渲染的 DOM 内容
  },
  methods: {
    a(){}
  }
})

beforeCreate

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

created

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

beforeMount

在挂载开始之前被调用:相关的 render 函数首次被调用。$el 属性已经可见,但还是原来的 DOM,并非是新创建的。

mounted

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

注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted

mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
  })
}

存在期

存在期会涉及到以下生命周期函数:

Vue 需要改变数据才会触发组件重新渲染,才会触发上面的存在期钩子函数。其中 beforeUpdateupdated 中间会触发 render 函数。

例子请看 http://jsrun.net/8ZyKp/edit

// 需要点击更新按钮
// 连续点击更新按钮,都会是 2 秒后不点击更新才会输出 “2 秒没更新了”
// 输出请看 右下角 Console 命令行工具
new Vue({
  el: '#dynamic-component-demo',
  data: {
    num: 2,
  },
  beforeUpdate(){
    clearTimeout(this.clearTimeout);
    this.clearTimeout = setTimeout(function(){
      console.log("2 秒没更新了");
    },2000);
    console.log("beforeUpdate",this.num,this.$el.innerText);
    // 第一次点击更新,输出为 beforeUpdate,3,点击更新 2
  },
  updated(){
    console.log("updated",this.num,this.$el.innerText);
    // 第一次点击更新,输出为 updated,3,点击更新 3
  },
  methods: {
    updateComponent(){
      this.num++;
    }
  }
})

beforeUpdate

数据更新时,虚拟 DOM 变化之前调用,这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

请不要在此函数中更改状态,否则会触发死循环。

updated

数据更新和虚拟 DOM 变化之后调用。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性watcher 取而代之。

和 mounted 一样, updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated

updated: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been re-rendered
  })
}

请不要在此函数中更改状态,否则会触发死循环。

销毁期

销毁期会涉及到以下生命周期函数:

例子请看 http://jsrun.net/QZyKp/edit

// 切换 tab,看右下角 console 输出
Vue.component('tab-home', { 
    template: '<div>Home component</div>',
  beforeDestroy(){
    console.log("tab-home","beforeDestroy");
  },
  destroyed(){
    console.log("tab-home","destroyed");
  },
})
Vue.component('tab-posts', { 
    template: '<div>Posts component</div>',
  beforeDestroy(){
    console.log("tab-posts","beforeDestroy");
  },
  destroyed(){
    console.log("tab-posts","destroyed");
  },
})
Vue.component('tab-archive', { 
    template: '<div>Archive component</div>',
  beforeDestroy(){
    console.log("tab-archive","beforeDestroy");
  },
  destroyed(){
    console.log("tab-archive","destroyed");
  },
})

new Vue({
  el: '#dynamic-component-demo',
  data: {
    currentTab: 'Home',
    tabs: ['Home', 'Posts', 'Archive']
  },
  computed: {
    currentTabComponent: function () {
      return 'tab-' + this.currentTab.toLowerCase()
    }
  }
})

beforeDestroy

实例销毁之前调用,在这一步,实例仍然完全可用。一般在这里移除事件监听器、定时器等,避免内存泄漏

destroyed

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

所以如果需要用到 Vue 实例指示的所用绑定的东西,需要在 beforeDestroy 中使用。这么说,destroyed 函数能做的事,在 beforeDestroy 也能做,所以没必要在 destroyed 函数中处理。

其他不常用的生命周期函数

  • activated

    当组件激活的时候调用,可以参考<a>构建组件 - keep-alive</a>

  • deactivated

    当组件停用的时候调用,可以参考<a>构建组件 - keep-alive</a>

  • errorCaptured

    这个生命钩子详细请看<a>官网</a>,2.5.0 新增的,当捕获一个来自子孙组件的错误时被调用。

使用注意

生命周期函数请不要使用 ES6 箭头函数,否则 this 指向会有问题。

请看这个例子 http://jsrun.net/cZyKp/edit

// 输出请看 右下角 Console 命令行工具
new Vue({
  el: '#dynamic-component-demo',
  data: {
    num: 2,
  },
  created: ()=>{
    console.log("created",this);
    // 输出为 created,[object Window]
    // this 指向不是 Vue 实例而是父级 this
  }
})

参考文章

  • 实例生命周期钩子
  • <a>如何解释vue的生命周期才能令面试官满意?</a>
  • <a>vue生命周期详解</a>

[转载]原文链接:https://segmentfault.com/a/1190000019209717

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-65176.html

文章标题:Vue 组件生命周期钩子函数

相关文章
JavaScript初学者必看“箭头函数”
本文我们介绍箭头 (arrow) 函数的优点。 更简洁的语法 我们先来按常规语法定义函数: function funcName(params) { return params + 2; } funcName(2); &#x2F;&#...
2017-05-26
最细致的vue.js基础语法 值得收藏!
介绍 前段时间接触到一个库叫做Vue.js, 个人感觉很棒,所以整理了一篇博文做个介绍。 Vue读音/vju:/,和view类似。是一个数据驱动的web界面库。Vue.js只聚焦于视图层,可以很容易的和其他库整合。代码压缩后只有24kb。 ...
2017-03-21
vue-awesome-swiper的使用以及API整理
一、先说一个看关于vue-awesome-swiper的一个坑 vue项目的package.json中显示的&lt;span style=“color: orange;”&gt;“vue-awesome-swiper”: “^2.5.4”&...
2018-04-26
详解angular2封装material2对话框组件
1. 说明 angular-material2自身文档不详,控件不齐,使用上造成了很大的障碍。这里提供一个方案用于封装我们最常用的alert和confirm组件。 2. 官方使用方法之alert ①编写alert内容组件 @Componen...
2017-03-13
mpvue 小程序如何开启下拉刷新,上拉加载?
https://developers.weixin.qq.com/miniprogram/dev/api/pulldown.html#onpulldownrefresh 小程序API 微信小程序之下拉加载和上拉刷新 微信小程序下拉加载和上拉...
2018-05-25
常用的Javascript函数
软件界面采用WEB界面,因此要用到Javascript.一些通用JS函数整理了下:) &#x2F;*判断浏览器版本*&#x2F; var w3c = (document.getElementById) ? true : false; var...
2015-11-11
vue使用watch 观察路由变化,重新获取内容
问题背景: 点击用户头像 =&gt; 进入用户个人中心,在用户个人中心里点击其他用户的头像,我希望显示被点击用户的个人中心,但只看到了路由参数在发生变化,页面内容并没有更新。如图: 页面代码如下: &lt;script&gt; exp...
2017-03-13
js使用split函数按照多个字符对字符串进行分割的方法
本文实例讲述了js使用split函数按照多个字符对字符串进行分割的方法。分享给大家供大家参考。具体分析如下: js中的split()函数可以对字符串按照指定的符号进行分割,但是如果字符串中存在多个分割符号,js的split()函数是否还可以...
2017-03-21
在 mpvue 使用 echarts 小程序组件
具体操作 下载 echarts-for-weixin 。 把其 ec-canvas 目录移动到 mpvue 项目的 static 目录下。 对 ec-canvas/ec-canvas.js 进行小调整,考虑提 pr 到 ec-c...
2018-03-11
Vue 短信验证码组件开发详解
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 Vue.js 自身不是一个全能框架——它只聚焦于视图层。因此...
2017-03-17
回到顶部