• 详解Vue生命周期


    正文

    Vue实例的生命周期全过程(图)

    (这里的红边圆角矩形内的都是对应的Vue实例的钩子函数)

    在beforeCreate和created钩子函数间的生命周期

    在beforeCreate和created之间,进行数据观测(data observer) ,也就是在这个时候开始监控data中的数据变化了,同时初始化事件
     
     

    created钩子函数和beforeMount间的生命周期

    对于created钩子函数和beforeMount间可能会让人感到有些迷惑,下面我就来解释一下:

    el选项的有无对生命周期过程的影响

    首先系统会判断对象中有没有el选项
    有el选项,则继续编译过程
    没有el选项,则停止编译,也意味着暂时停止了生命周期,直到vm.$mount(el)
    下面我展示一下:
    复制代码
    new Vue({
      el: '#app',
      beforeCreate: function () {
        console.log('调用了beforeCreat钩子函数')
      },
      created: function () {
        console.log('调用了created钩子函数')
      },
      beforeMount: function () {
        console.log('调用了beforeMount钩子函数')
      },
      mounted: function () {
        console.log('调用了mounted钩子函数')
      }
    })
    复制代码
    demo如下:
    可以看到,在el选项填写且正确的时候,生命周期将正常进行
     
    而当我们把el去掉:
    复制代码
    new Vue({
      beforeCreate: function () {
        console.log('调用了beforeCreat钩子函数')
      },
      created: function () {
        console.log('调用了created钩子函数')
      },
      beforeMount: function () {
        console.log('调用了beforeMount钩子函数')
      },
      mounted: function () {
        console.log('调用了mounted钩子函数')
      }
    })
    复制代码
    demo:
     
    可以看到,生命周期的钩子函数执行到created就结束了
    而当我们不加el选项,但是手动执行vm.$mount(el)方法的话,也能够使暂停的生命周期进行下去,例如:
    复制代码
    var vm = new Vue({
      beforeCreate: function () {
        console.log('调用了beforeCreat钩子函数')
      },
      created: function () {
        console.log('调用了created钩子函数')
      },
      beforeMount: function () {
        console.log('调用了beforeMount钩子函数')
      },
      mounted: function () {
        console.log('调用了mounted钩子函数')
      }
    })
    vm.$mount('#app')
    复制代码
    demo如下,可以看到,这个时候虽然对象中没有el参数,但通过$mount(el)动态添加的方式,也能够使生命周期顺利进行
     

    template参数选项的有无对生命周期的影响

     
    1.如果Vue实例对象中有template参数选项,则将其作为模板编译成render函数
    2.如果没有template参数选项,则将外部的HTML作为模板编译(template),也就是说,template参数选项的优先级要比外部的HTML高
    3.如果1,2条件都不具备,则报错
     
    我们可以把模板写在template参数选项中:
    new Vue({
      el: '#app',
      template: '<div id="app"><p>模板在templated参数中找到了哟~</p></div>'
    })
    demo:
     
    也可以把参数选项写在外部HTML中,像这样:
     
    外部HTML:
    <div id="app"><p>模板是在外部HTML中找到的~</p></div>
    创建对象实例:
    new Vue({
      el: '#app'
    })
    demo:
    那么有趣的问题来了,当模板同时放在template参数选项和外部HTML中,会怎样呢?
    例如:
    外部HTML:
    <div id="app"><p>模板是在外部HTML中找到的~</p></div>
     
    创建Vue实例(包含template参数选项)
    new Vue({
      el: '#app',
      template: '<div id="app"><p>模板在templated参数中找到了哟~</p></div>'
    })
    demo如下:
    很显然,正如我上面下的结论一样,最终显示的是“模板在templated参数中找到了哟~”而不是“模板是在外部HTML中找到的~”,因为template参数的优先级比外部HTML的优先级要高
     
    【注意】
    1.为什么判断el要发生在判断template前面呢
     
    因为Vue需要通过el的“选择器”找到对应的template。总结一下上述的过程,Vue通过el参数去找到对应的template。然后,根据el参数给出的“选择器”,首先去Vue实例对象本身的template选项参数中找,如果没有template参数,则到外部HTML中寻找,找到后将模板编译成render函数
     
    2.实际上,在Vue中,有render函数这个选项,它以createElement作为参数,做渲染操作。当然你也可以不调用createElement,而直接嵌入JSX(学习react的同学对此应该很熟悉吧)。
    复制代码
    new Vue({
      el: '#demo',
      render (createElement) {
        return (....)
      }
    })
    复制代码
    【注意】render选项参数比template更接近Vue解析器!所以综合排列如下:
    render函数选项  > template参数  > 外部HTML
     

    Vue的编译过程——把模板编译成 render 函数

    Vue的编译实际上是指Vue把模板编译成 render 函数的过程
     
    我们可以通过Vue.compile这个实时编译模板的函数来看一看:
    用官方文档的例子做个解释:
    复制代码
    <div>
      <header>
        <h1>I'm a template!</h1>
      </header>
      <p v-if="message">
        {{ message }}
      </p>
      <p v-else>
        No message.
      </p>
    </div>
    复制代码
      
    会被渲染成
    function anonymous() {
      with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])}
    }

    beforeMount和mounted钩子函数间的生命周期

      对于这一点,我也感到有些迷惑,百度后之后也没什么头绪,最后我思考的结果是这样的:正因为render函数和template选项的“优先级”比外部HTML要高,所以,最后一般会存在一个外部HTML模板被Vue实例本身配置的模板所“替代”的过程也就是上图所说的 “replace”
     
    (如果大家有不同意见也可以在评论处一起讨论)
     

    beforeUpdate钩子函数和updated钩子函数间的生命周期

     
    在Vue中,数据更改会导致虚拟 DOM 重新渲染,并先后调用beforeUpdate钩子函数和updated钩子函数
     
    但要注意一点:重渲染(调用这两个钩子函数)的前提是被更改的数据已经被写入模板中!!(这点很重要)
    例如:
    复制代码
    var vm = new Vue({
      el: '#app',
      data: {
        number: 1
      },
      template: '<div id="app"><p></p></div>',
      beforeUpdate: function () {
        console.log('调用了beforeUpdate钩子函数')
      },
      updated: function () {
        console.log('调用了updated钩子函数')
      }
    })
     
    vm.number = 2
    复制代码
     
    控制台上并没有如我们预料那样输出调用两个钩子函数的文本
    而当我们改成
    复制代码
    var vm = new Vue({
      el: '#app',
      data: {
        number: 1
      },
      // 在模板中使用number这个数据
      template: '<div id="app"><p>  {{ number }} </p></div>',
      beforeUpdate: function () {
        console.log('调用了beforeUpdate钩子函数')
      },
      updated: function () {
        console.log('调用了updated钩子函数')
      }
    })
     
    vm.number = 2
     
    复制代码
     
    这个时候,调用两个钩子函数的文本就被输出来了
    总之,只有Vue实例中的数据被“写入”到我们的模板中,它的改变才可以被Vue追踪,重渲染从而调用 beforeUpdate钩子函数和updated钩子函数
     

    beforeDestroy和destroyed钩子函数间的生命周期

     
    beforeDestroy钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。
     
    destroyed钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
     
    【注意】就如同调用在Vue实例上调用$mounted会使暂停的生命周期继续一样,调用$destroy()会直接销毁实例
     
     
     
     
     
     
    « 上一篇:【npm】伙计,给我来一杯package.json!不加糖
    » 下一篇:【Vue】谈Vue的依赖追踪系统 ——搞懂methods watch和compute的区别和联系
    posted @ 2017-07-16 22:26 外婆的彭湖湾 阅读(5358) 评论(13) 编辑 收藏

     
  • 相关阅读:
    网络诊断工具:[tcpdump]
    网络诊断工具:iproute
    C语言编译全过程
    (Ruby)Ubuntu12.04安装Rails环境
    (Life)牛人的学习方法(转译文)
    (WPF)WPF事件要点WPF宝典笔记
    (WPF)依赖属性要点WPF宝典笔记
    (DP)降低代码重构的风险(转载)
    (WPF)路由事件要点WPF宝典笔记
    JDBC,MYBATIS,Hibernate性能对比!
  • 原文地址:https://www.cnblogs.com/itrena/p/8861431.html
Copyright © 2020-2023  润新知