美文网首页vue传值框架Vuejs
vue生命周期钩子函数的正确使用方式

vue生命周期钩子函数的正确使用方式

作者: 任无名F | 来源:发表于2017-07-16 14:10 被阅读1924次
    先上图
    vue的生命周期
    遇到的一个问题

    在我的项目中,常用的生命周期钩子函数一直都是mounted,对于大部分情况,都是屡试不爽、捷报频传~

    但是在前几天却遭遇了一个意外,我在mounted中获取后台数据并更新data,在template中把data.fullname与一个p元素的innerHTML绑定,这是一个简单到不能再简单,普通到不能更普通的操作,打开浏览器一看,完美!fullname的数据正常显示在p元素中,没有任何问题,可是……咦,控制台怎么报错了?

    报错信息

    报错信息的大致意思是,data是null,无法获取到null的fullname属性,可是数据明明正常显示了呀,而且我们不是从后台请求数据并给data赋值了嘛?

    经过一番排查,发现原因有两处:

    1. 初始化时,给data的值是null
      data () {
        return {
          data: null,
      },
    
    1. vue渲染template的时间在beforeMount之后,mounted之前,所以渲染template时data值为null,故而报错;但是待后台数据请求成功给data赋值后,p元素能监听到数据的变化,然后更新其innerHTML,所以UI看起来是很正常的
    解决方案

    所以解决方案是非常简单的,只需要保证渲染template的时候,data已经拿到后台数据就可以了,所以可以把mounted钩子函数修改为beforeMount,或者其他更早被调用的钩子函数:beforeCreated、created等


    后来经过验证,上述的解决方案是错误的,因为它只针对同步代码有效果。而ajax请求是异步操作,回调函数的执行时间不能确定,所以即使放在created钩子函数中,也不能保证在mounted之前完成数据的请求……

    所以最终的解决方案是,给p标签加一个v-if,待data不为null时再进行渲染,但并不算很优雅。

    不知道vue的生命周期钩子函数是否支持promise或者async/await,如果大神们有更好的解决方案,欢迎交流~

    总结

    一点小小的感悟,vue生命周期钩子函数的使用并非一成不变的,要根据不同的应用场景而有所改变,稍微总结一下:

    1. beforeCreate:在实例初始化之后,**数据观测(data observer) ** 和 event/watcher事件配置 之前被调用,注意是 之前,此时data、watcher、methods统统滴没有。
      这个时候的vue实例还什么都没有,但是$route对象是存在的,可以根据路由信息进行重定向之类的操作。

    2. created:在实例已经创建完成之后被调用。在这一步,实例已完成以下配置:数据观测(data observer)属性和方法的运算watch/event 事件回调。然而,挂载阶段还没开始,$el属性目前不可见。
      此时 this.$data 可以访问,watcher、events、methods也出现了,若根据后台接口动态改变data和methods的场景下,可以使用。

    3. beforeMount:在挂载开始之前被调用,相关的 render 函数 首次被调用。但是render正在执行中,此时DOM还是无法操作的。我打印了此时的vue实例对象,相比于created生命周期,此时只是多了一个$el的属性,然而其值为undefined。
      使用场景我上文已经提到了,页面渲染时所需要的数据,应尽量在这之前完成赋值。

    4. mounted:在挂载之后被调用。在这一步 创建vm.$el并替换el,并挂载到实例上。(官方文档中的 “如果root实例挂载了一个文档内元素,当mounted被调用时vm.$el也在文档内” 这句话存疑)
      此时元素已经渲染完成了,依赖于DOM的代码就放在这里吧~比如监听DOM事件。

    5. beforeUpdate:$vm.data更新之后,虚拟DOM重新渲染 和打补丁之前被调用。
      你可以在这个钩子中进一步地修改$vm.data,这不会触发附加的重渲染过程。

    6. updated:虚拟DOM重新渲染 和打补丁之后被调用。
      当这个钩子被调用时,组件DOM的data已经更新,所以你现在可以执行依赖于DOM的操作。但是不要在此时修改data,否则会继续触发beforeUpdate、updated这两个生命周期,进入死循环!

    7. beforeDestroy:实例被销毁之前调用。在这一步,实例仍然完全可用。
      实例要被销毁了,赶在被销毁之前搞点事情吧哈哈~

    8. destroyed:Vue实例销毁后调用。此时,Vue实例指示的所有东西已经解绑定,所有的事件监听器都已经被移除,所有的子实例也已经被销毁。
      这时候能做的事情已经不多了,只能加点儿提示toast之类的东西吧。

    :beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed这几个钩子函数,在服务器端渲染期间不被调用。

    相关文章

      网友评论

      • nextliving:总结的很细致,java工程师都能看懂:+1:
      • 秋夜已凉:这么多坑啊
      • 葡萄果茶:这个问题我也遇见过。就是请求数据的时候,请求的是个数组,但data里对应的变量写了个对象。然后对数组迭代,程序运行没问题,但控制台一直报错这不是个数组。后来才找到原来在data必须也写成数组
      • bd1bd0405fe0:v-if="data"是个好办法,最起码节省了很多代码,我现在干的项目也碰到了这个问题,我都是先把数据的格式在data里面写好,不用null但是这样多了很多代码,数据格式复杂的情况下很费事
        任无名F:恩 你这种做法从前我也干过 觉得vue开发很多时候还是没有做到最佳实践 只能在实际项目中思考求证啦~

      本文标题:vue生命周期钩子函数的正确使用方式

      本文链接:https://www.haomeiwen.com/subject/peptkxtx.html