最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【译】Vue3生命周期钩子(hooks)完整指南

    正文概述 掘金(旭旭乐是只小菜鸡)   2021-01-01   1246

    【译】Vue3生命周期钩子(hooks)完整指南

    原文地址:(A Complete Guide to Vue Lifecycle Hooks in Vue3 – LearnVue)

    Vue3与Vue2的生命周期钩子(hooks)非常相似——我们仍可以在相同的场景下使用相同(或类似)的钩子。

    如果项目使用Options API方式构建,那就无须修改任何生命周期相关的代码。这是因为Vue3在设计时已对先前版本做了兼容处理。

    然而,如果使用Composition API方式(构建大型Vue项目时非常有用)构建项目,生命周期钩子则会略有不同。

    通过阅读本文,你将了解如何在Options API和Composition API中使用生命周期钩子,并且让你书写更优秀的代码。

    冲!

    什么是Vue的生命周期钩子

    首先,让我们看一下Options API和Composition API的Vue3生命周期钩子示意图。在我们深入了解之前,能有一个整体上的概念。

    【译】Vue3生命周期钩子(hooks)完整指南

    基本上,每个主要的(main)Vue生命周期事件会对应2个钩子函数,分别在事件开始前和事件结束后调用。在Vue app中你可以应用4个主要事件(8个主要钩子(main hooks)函数)。

    • Creation ——组件创建时运行
    • Mounting ——挂载在DOM时运行
    • Updates ——响应数据修改时运行
    • Destruction ——元素销毁前运行

    在Options API中使用生命周期钩子

    使用Options API时,生命周期钩子暴露在Vue实例的选项中。不需要我们导入任何东西,只需调用对应的函数并书写相关生命周期的代码即可。

    举个例子,假设我们想要访问mounted()updated()生命周期钩子,代码可能如下所示:

    <script>     
       export default {         
          mounted() {             
             console.log('mounted!')         
          },         
          updated() {             
             console.log('updated!')         
          }     
       }
    </script> 
    

    是不是非常简单?

    那么,接下来我们继续在Composition API中使用Vue3的生命周期钩子。

    在Composition API中使用生命周期钩子

    在Composition API中,我们需要先导入对应的生命周期钩子才能使用它。这么做,是为了让我们的项目尽可能的轻量化。

    import { onMounted } from 'vue'
    

    除了beforeCreatecreated(被setup方法本身代替),共有9个Options API生命周期相对应的方法可以在setup中使用。

    • onBeforeMount——挂载开始前调用
    • onMount——挂载后调用
    • onBeforeUpdate——当响应数据改变,且重新渲染前调用
    • onUpdated——重新渲染后调用
    • onBeforeUnmount——Vue实例销毁前调用
    • onUnmounted——实例销毁后调用
    • onActivated——当keep-alive组件被激活时调用
    • onDeactivated——当keep-alive组件取消激活时调用
    • onErrorCaptured——从子组件中捕获错误时调用

    当我们需要导入并访问这些钩子函数时,代码可能如下所示:

    <script>
    import { onMounted } from 'vue'
    
    export default {
       setup () {
         onMounted(() => {
           console.log('mounted in the composition api!')
         })
       }
    }
    </script>
    

    将Vue2代码更新为Vue3生命周期钩子

    你可以方便的在 Vue3 Composition API docs中查看Vue2到Vue3生命周期的映射。并且,我认为这也是明确如何改变和使用它们的最有效的方式之一。

    • beforeCreate -> setup()
    • created -> setup()
    • beforeMount -> onBeforeMount
    • mounted -> onMounted
    • beforeUpdate -> onBeforeUpdate
    • updated -> onUpdated
    • beforeDestroy -> onBeforeUnmount
    • destroyed -> onUnmounted
    • errorCaptured -> onErrorCaptured

    深入了解每个生命周期钩子

    现在我们已知两个重要的事情:

    1. 我们能够使用的各种生命周期
    2. 如何在Options API和Composition API中使用它们

    接下来,让我们深入每个生命周期钩子中,了解如何使用它们,各个钩子中可以写什么样的代码,并且聊聊介于Options API和Composition API中的不同。

    Creation钩子——VueJS生命周期的起始

    Creation钩子是你启动项目时触发的第一个事件。

    beforeCreate() ——Options API

    因为created钩子是用来初始化响应数据和事件的,所以你不能在beforeCreate钩子里访问任何组件的响应式数据和事件。

    观察以下代码示例:

    export default {
       data() { 
         return { 
           val: 'hello'    
         }
       },
       beforeCreate() {     
         console.log('Value of val is: ' + this.val)   
       }
    }
    

    因为此时数据还未初始化,所以val的值是undefined,并且你也不能在此函数中调用组件中的其他方法。

    如果你想要查看能使用的属性列表,我建议通过console.log(this)查看哪些属性已经初始化。这对Options API的其他钩子函数也同样有效。

    beforeCreate对那些不需要分配数据(data)的逻辑和API调用来说十分有用。如果我们此时对数据(data)赋值,那么这些值将在状态初始化后丢失。

    created() – Options API

    此时,我们已经可以访问组件的数据和事件。因此,将上例中的beforeCreate替换为created,我们能够看到输出有的改变。

    export default {
       data() { 
         return { 
           val: 'hello'    
         }
       },
       created() {     
         console.log('Value of val is: ' + this.val)   
       }
    }
    

    因为此时已经初始化,所以上例将输出 Value of val is: hello

    当需要处理响应式数据读/写(reading/writing)时created方法非常有用。举个例子,如果你需要完成一个API调用并存储它的值,那么你应该将它写在这里。

    这将比在mounted中处理来的更好,因为它在Vue的初始化进程中更早触发,并且你也能读写所有的数据。

    那Composition API的Creation钩子呢?

    在Composition API的生命周期钩子中,beforeCreatecreatedsetup()方法代替。这意味着你应该将对应的代码写在setup方法中。

    将刚刚created生命周期钩子重写为如下所示

    import { ref } from 'vue'
    
    export default {
       setup() {    
         const val = ref('hello') 
         console.log('Value of val is: ' + val.value)       
         return {         
           val
         }
       }
    }
    

    Mounting钩子——访问DOM

    mounting钩子处理组件的挂载和渲染。这是我们在项目和应用程序中最常用的一组钩子。

    beforeMount() and onBeforeMount()

    在组件DOM实际渲染和挂载前触发。在此阶段,根元素(root element)还未存在。在Options API中,可以通过this.$el访问。而在Composition API中,你必需通过ref来指定根元素。

    export default {
       beforeMount() {
         console.log(this.$el)
       }
     }
    

    Composition代码可能如下所示:

    <template>
       <div ref='root'>
         Hello World
       </div>
    </template> 
    

    通过ref访问的script代码如下:

    import { ref, onBeforeMount } from 'vue'
    
    export default {
       setup() {
          const root = ref(null) 
          onBeforeMount(() => {   
             console.log(root.value) 
          }) 
          return { 
             root
          }
        },
        beforeMount() {
          console.log(this.$el)
        }
     }
    

    因为此时app.$el还未创建,上述代码的输出将是undefined。

    于此同时,我们更推荐在created()setup中执行你的API调用。两者具有相同的组件变量访问,但是beforeMount会在created之后调用。

    mounted() and onMounted()

    在组件第一次渲染时调用。此时,组件已经可以访问DOM。

    同样,在Options API中,我们使用this.$el访问我们的DOM,而在Composition API的生命周期钩子中,我们需要借助refs去访问相应DOM。

    import { ref, onMounted } from 'vue'
     
    
     export default {
       setup() {    /* Composition API */
     
         const root = ref(null)
     
         onMounted(() => {
           console.log(root.value)
         })
     
    
         return {
           root
         }
       },
       mounted() { /* Options API */
         console.log(this.$el)
       }
     }
    

    Update钩子——VueJS生命周期中的响应

    无论何时响应数据被修改,updated生命周期事件都将触发,并且触发渲染更新。

    beforeUpdate() and onBeforeUpdate()

    在数据修改且组件重渲染之前执行。这是任何更改还未发生前,手动修改DOM的好地方。

    beforeUpdate对追踪组件的编辑次数时非常有用,甚至可以通过追踪对应的操作来创建一个“撤销”功能。

    updated() and onUpdated()

    updated方法在DOM更新后调用一次。这是一段beforeUpdate和updated的基本代码

     <template>
        <div>
          <p>{{val}} | edited {{ count }} times</p>
          <button @click='val = Math.random(0, 100)'>Click to Change</button>
        </div>
     </template>
    

    相对应的script代码

     export default {
       data() {
          return {
            val: 0
          }
       },
       beforeUpdate() {
          console.log("beforeUpdate() val: " + this.val)
       },
       updated() {
          console.log("updated() val: " + this.val
       }
     }
    

    import { ref, onBeforeUpdate, onUpdated } from 'vue'
     
     export default {
       setup () {
         const count = ref(0)
         const val = ref(0)
     
         onBeforeUpdate(() => {
           count.value++;
           console.log("beforeUpdate");
         })
     
         onUpdated(() => {
           console.log("updated() val: " + val.value)
         })
     
         return {
           count, val
         }
       }
     } 
    

    这些方法很有用,但多数情况我们可能会通过监听器(watchers)去检测对应数据的改变。因为监听器可以很好的提供数据更改时的旧值和新值。

    另一种方式是通过计算属性来改变元素的状态。

    Destruction钩子——清理

    destruction钩子在组件被移除并需要清理一些待释放的功能时使用。这是删除事件监听并且防止内存溢出的好地方。

    beforeUnmount() and onBeforeUnmounted()

    触发在组件开始销毁之前,在此会进行绝大多数的清理工作。在此阶段,你的组件仍然拥有所有的功能,任何东西都还未被销毁。

    举一个删除事件监听的例子,Options API方式如下

    export default {
       mounted() {
         console.log('mount')
         window.addEventListener('resize', this.someMethod);
       },
       beforeUnmount() {
         console.log('unmount')
         window.removeEventListener('resize', this.someMethod);
       },
       methods: {
          someMethod() {
             // do smth
          }
       }
    } 
    

    Composition API方式

     import { onMounted, onBeforeUnmount } from 'vue' 
    
     export default {
       setup () {
     
         const someMethod = () => {
           // do smth
         }
     
         onMounted(() => {
           console.log('mount')
           window.addEventListener('resize', someMethod);
         })
     
         onBeforeUnmount(() => {
           console.log('unmount')
           window.removeEventListener('resize', someMethod);
         })
     
       }
     } 
    

    可以在Vite,vue-cli,或任何支持热加载的环境中查看这些行为的执行。当你更新代码时,你的组件会销毁,并重新挂载。

    unmounted() and onUnmounted()

    此时,大多数组件和它的属性已经销毁,所以你能做的不多。同样,我打印一段数据去确切观察发生了什么。

    import { onUnmounted } from 'vue'
    
    export default {
      setup () { /* Composition API */
    
        onUnmounted(() => {
          console.log('unmounted')
        })
    
      },
      unmounted() { /* Options API */
        console.log('unmounted')
      }
    }
    

    Activation钩子——管理Keep-Alive组件

    keep-alive标签是对动态组件的包装元素。它保存一段组件实例的缓存引用,如此Vue就不需要在每次动态组件(dynamic component)改变时创建一个新的实例。

    对于这种特殊的使用情况,Vue提供了两个生命周期钩子。

    activated() and onActivated()

    无论何时动态组件被“重新激活”(意味着此时是动态组件激活视图)时该钩子方法都将被调用。

    举个例子,如果我们使用keep-alive管理不同的tab视图,每次我们切换tab时,当前的tab将会触发activated钩子。

    假设我们有以下用keep-alive包装的 动态组件setup。

    <template>
       <div>
         <span @click='tabName = "Tab1"'>Tab 1 </span>
         <span @click='tabName = "Tab2"'>Tab 2</span>
         <keep-alive>
           <component :is='tabName' class='tab-area'/>
         </keep-alive>
       </div>
    </template>
    
    <script>
    import Tab1 from './Tab1.vue'
    import Tab2 from './Tab2.vue'
    
    import { ref } from 'vue'
    
    export default {
      components: {
        Tab1,
        Tab2
      },
      setup () { /* Composition API */
        const tabName = ref('Tab1')
    
        return {
          tabName
        }
      }
    }
    </script>
    

    在我们的Tab1.vue组件中,我们能够如下访问activation钩子。

    <template>
     <div>
     <h2>Tab 1</h2>
     <input type='text' placeholder='this content will persist!'/>
     </div>
    </template>
    
    <script>
    import { onActivated } from 'vue'
    
    export default {
     setup() {
        onActivated(() => {
           console.log('Tab 1 Activated')
        })
     }
    } 
    </script>
    

    deactivated() and onDeactivated()

    和你想象的一样,视图不在动态组件中继续保持激活时触发此钩子。

    该钩子在某些情况下非常有用,例如特定视图失去焦点时,保存用户数据和触发动画。

    我们能够如下所示,捕获该生命周期钩子

    import { onActivated, onDeactivated } from 'vue'
    
    export default {
      setup() {
        onActivated(() => {
           console.log('Tab 1 Activated')
        })
    
        onDeactivated(() => {
           console.log('Tab 1 Deactivated')
        })
      }
    }
    

    现在,当我们切换tab时,每个动态组件的状态都将被保存。

    【译】Vue3生命周期钩子(hooks)完整指南

    好耶!

    Vue3 Debug Hooks

    Vue3为我们提供了两个调试时的钩子:

    1. onRenderTracked
    2. onRenderTriggered

    这两个事件都携带一个DebuggerEvent参数,以允许我们获悉是什么触发了Vue实例的重新渲染。

    export default {
        onRenderTriggered(e) {
           debugger
           // 检测什么依赖造成了组件的重新渲染
        }
    }
    

    总结

    无论是使用Options API还是Composition API,不能仅知道你能用什么生命周期,还要知道为什么使用它们。

    许多问题都能在多个生命周期钩子中解决。但是,最好知道哪个生命周期是最适合你当下的情况。不管怎样,你都需要深思熟虑,并对使用特定的生命周期有充足的理由。

    我希望借此文章对你理解生命周期函数,并且在你项目中应用它们时有所帮助。

    Happy coding!


    起源地下载网 » 【译】Vue3生命周期钩子(hooks)完整指南

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元