乐趣区

关于javascript:Vue-3-生命周期完整指南

作者:Michael Thiessen
译者:前端小智
起源:news

点赞再看 ,微信搜寻【大迁世界】,B 站关注【前端小智】 这个没有大厂背景,但有着一股向上踊跃心态人。本文 GitHub https://github.com/qq44924588… 上曾经收录,文章的已分类,也整顿了很多我的文档,和教程材料。

最近开源了一个 Vue 组件,还不够欠缺,欢送大家来一起欠缺它,也心愿大家能给个 star 反对一下,谢谢各位了。

github 地址:https://github.com/qq44924588…

Vue2 和 Vue3 中的生命周期钩子的工作形式十分类似,咱们依然能够拜访雷同的钩子,也心愿将它们能用于雷同的场景。

如果我的项目应用 选项 API,就不用更改任何代码了,因为 Vue3 兼容以前的版本。

当然,咱们用 Vue3 就是要用它的 组合 API组合 API中拜访这些钩子的形式略有不同,组合 API在较大的 Vue 我的项目中特地有用。

本文次要内容:

  1. Vue 生命周期钩子有哪些
  2. 选项 API中应用 Vue 生命周期钩子
  3. 组合 API中应用 Vue 3 生命周期钩子
  4. 将 Vue2 的生命周期钩子代码更新到 Vue3
  5. 看看 Vue 2 和 Vue 3 中的每个生命周期钩子

    1. 创立
    2. 挂载
    3. 更新
    4. 卸载
    5. 激活
  6. Vue 3 中的新调试钩子

Vue 生命周期钩子有哪些

首先,来看一下 选项 API 和 组合 API 中 Vue 3 生命周期钩子的图表。在深刻细节之前,这能加深咱们的了解。

实质上,每个次要 Vue 生命周期事件被分成两个钩子,别离在事件之前和之后调用。Vue 应用程序中有 4 个次要事件(8 个次要钩子)。

  • 创立 — 在组件创立时执行
  • 挂载 — DOM 被挂载时执行
  • 更新 — 当响应数据被批改时执行
  • 销毁 — 在元素被销毁之前立刻运行

选项 API中应用 Vue 生命周期钩子

应用 选项 API,生命周期钩子是被裸露 Vue 实例上的选项。咱们不须要导入任何货色,只须要调用这个办法并为这个生命周期钩子编写代码。

例如,假如咱们想拜访 mounted()updated()生命周期钩子,能够这么写:

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

组合 API中应用 Vue 3 生命周期钩子

在组合 API 中,咱们须要将生命周期钩子导入到我的项目中,能力应用,这有助于放弃我的项目的轻量性。

// 组合 API
import {onMounted} from 'vue'

除了 beforecatecreated(它们被 setup 办法自身所取代),咱们能够在 setup 办法中拜访的 API 生命周期钩子有 9 个选项:

  • onBeforeMount – 在挂载开始之前被调用:相干的 render 函数首次被调用。
  • onMounted – 组件挂载时调用
  • onBeforeUpdate – 数据更新时调用,产生在虚构 DOM 打补丁之前。这里适宜在更新之前拜访现有的 DOM,比方手动移除已增加的事件监听器。
  • onUpdated – 因为数据更改导致的虚构 DOM 从新渲染和打补丁,在这之后会调用该钩子。
  • onBeforeUnmount – 在卸载组件实例之前调用。在这个阶段,实例依然是齐全失常的。
  • onUnmounted – 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
  • onActivated – 被 keep-alive 缓存的组件激活时调用。
  • onDeactivated – 被 keep-alive 缓存的组件停用时调用。
  • onErrorCaptured – 当捕捉一个来自子孙组件的谬误时被调用。此钩子会收到三个参数:谬误对象、产生谬误的组件实例以及一个蕴含谬误起源信息的字符串。此钩子能够返回 false 以阻止该谬误持续向上流传。

应用事例:

// 组合 API
<script>
import {onMounted} from 'vue'

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

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

这个从 Vue2 到 Vue3 的生命周期映射是间接从 Vue 3 Composition API 文档中取得的:

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

深刻理解每个生命周期钩子

咱们当初理解了两件重要的事件:

  • 咱们能够应用的不同的生命周期钩子
  • 如何在选项 API 和组合 API 中应用它们

咱们深刻一下每个生命周期钩子,看看它们是如何被应用的,咱们能够在每个钩子中编写特定代码,来测试在 Options API 和 Composition API 中的各自的区别。

beforeCreate() – 选项 API

因为 创立 的挂钩是用于初始化所有响应数据和事件的事物,因而 beforeCreate 无法访问组件的任何响应数据和事件。

以上面的代码块为例:

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

val的输入值是 undefined,因为尚未初始化数据,咱们也不能在这调用组件办法。

如果你想查看可用内容的残缺列表,倡议只运行 console.log(this) 来查看已初始化的内容。当应用选项 API 时,这做法在其余钩子中也很有用。

created() – 选项 API

如果咱们要在组件创立时拜访组件的数据和事件,能够把下面的 beforeCreatecreated代替。

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

其输入为Value of val is: hello,因为咱们曾经初始化了数据。

在解决读 / 写反馈数据时,应用created 的办法很有用。例如,要进行 API 调用而后存储该值,则能够在此处进行此操作。

最好在这里执行此操作,而不是在mounted 中执行此操作,因为它产生在 Vue 的同步初始化过程中,并且咱们须要执行所有数据读取 / 写入操作。

那么组合 API 的创立钩子呢?

对于应用 组合 API 的 Vue3 生命周期钩子,应用 setup() 办法替换 beforecatecreated。这意味着,在这些办法中放入的任何代码当初都只在 setup 办法中。

// 组合 AP
import {ref} from 'vue'

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

beforeMount() and onBeforeMount()

在组件 DOM 理论渲染装置之前调用。在这一步中,根元素还不存在。在选项 API 中,能够应用 this.$els 来拜访。在组合 API 中,为了做到这一点,必须在根元素上应用ref

// 选项 API
export default {beforeMount() {console.log(this.$el)
   }
 }

组合 API 中应用 ref:

// 组合 API
<template>
   <div ref='root'>
     Hello World
   </div>
</template> 

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

mounted() and onMounted()

在组件的第一次渲染后调用,该元素当初可用,容许间接 DOM 拜访

同样,在 选项 API 中,咱们能够应用 this.$el 来拜访咱们的 DOM,在组合 API 中,咱们须要应用 refs 来拜访 Vue 生命周期钩子中的 DOM。

import {ref, onMounted} from 'vue'
 

 export default {setup() {    /* 组合 API */
 
     const root = ref(null)
 
     onMounted(() => {console.log(root.value)
     })
 

     return {root}
   },
   mounted() { /* 选项 API */
     console.log(this.$el)
   }
 } 

beforeUpdate() and onBeforeUpdate()

数据更新时调用,产生在虚构 DOM 打补丁之前。这里适宜在更新之前拜访现有的 DOM,比方手动移除已增加的事件监听器。

beforeUpdate对于跟踪对组件的编辑次数,甚至跟踪创立“吊销”性能的操作很有用。

updated() and onUpdated()

DOM 更新后,updated的办法即会调用。

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

选项 API 形式:

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

组合 API 的形式:

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}
   }
 }

这些办法很有用,然而对于更多场景,咱们须要应用的 watch 办法检测这些数据更改。watch 之所以好用,是因为它给出了更改后的数据的旧值和新值。

另一种抉择是应用计算属性来基于元素更改状态。

beforeUnmount() 和 onBeforeUnmounted()

在卸载组件实例之前调用。在这个阶段,实例依然是齐全失常的。

在 选项 API 中,删除事件侦听器的示例如下所示。

// 选项 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}
   }
} 
// 组合 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() 和 onUnmounted()

卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

import {onUnmounted} from 'vue'

export default {setup () { /* 组合 API */

    onUnmounted(() => {console.log('unmounted')
    })

  },
  unmounted() { /* 选项 API */
    console.log('unmounted')
  }
}

activated() and onActivated()

keep-alive 缓存的组件激活时调用。

例如,如果咱们应用 keep-alive 组件来治理不同的选项卡视图,每次在选项卡之间切换时,以后选项卡将运行这个 activated 钩子。

假如咱们应用 keep-alive 包装器进行以下动静组件。

<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 () { /* 组合 API */
    const tabName = ref('Tab1')

    return {tabName}
  }
}
</script>

Tab1.vue 组件外部,咱们能够像这样拜访 activated 钩子。

<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() 和 onDeactivated()

keep-alive 缓存的组件停用时调用。

这个钩子在一些用例中很有用,比方当一个特定视图失去焦点时保留用户数据和触发动画。

import {onActivated, onDeactivated} from 'vue'

export default {setup() {onActivated(() => {console.log('Tab 1 Activated')
    })

    onDeactivated(() => {console.log('Tab 1 Deactivated')
    })
  }
}

当初,当咱们在选项卡之间切换时,每个动静组件的状态都将被缓存和保留。

Vue3 调试钩子

Vue3 为咱们提供了两个可用于调试目标的钩子。

  1. onRenderTracked
  2. onRenderTriggered

这两个事件都带有一个debugger event,此事件通知你哪个操作跟踪了组件以及该操作的指标对象和键。

onRenderTracked

跟踪虚构 DOM 从新渲染时调用。钩子接管 debugger event 作为参数。此事件通知你哪个操作跟踪了组件以及该操作的指标对象和键。

<div id="app">
  <button v-on:click="addToCart">Add to cart</button>
  <p>Cart({{cart}})</p>
</div>
const app = Vue.createApp({data() {
    return {cart: 0}
  },
  renderTracked({key, target, type}) {console.log({ key, target, type})
    /* 当组件第一次渲染时,这将被记录下来:
    {
      key: "cart",
      target: {cart: 0},
      type: "get"
    }
    */
  },
  methods: {addToCart() {this.cart += 1}
  }
})

app.mount('#app')

renderTracked

当虚构 DOM 从新渲染为 triggered.Similarly 为renderTracked,接管 debugger event 作为参数。此事件通知你是什么操作触发了从新渲染,以及该操作的指标对象和键。

用法:

<div id="app">
  <button v-on:click="addToCart">Add to cart</button>
  <p>Cart({{cart}})</p>
</div>
const app = Vue.createApp({data() {
    return {cart: 0}
  },
  renderTriggered({key, target, type}) {console.log({ key, target, type})
  },
  methods: {addToCart() {
      this.cart += 1
      /* 这将导致 renderTriggered 调用
        {
          key: "cart",
          target: {cart: 1},
          type: "set"
        }
      */
    }
  }
})

app.mount('#app')

总结

无论你抉择应用选项 API 还是 组合 API,不仅要晓得要应用哪个生命周期挂钩,而且要晓得为什么要应用它,这一点很重要。

对于许多问题,能够应用多个生命周期钩子。然而最好晓得哪个是最适宜你用例的。无论如何,你都应该好好考虑一下,并有充沛的理由去抉择一个特定的生命周期钩子。

我心愿这能帮忙大家更多地了解生命周期钩子以及如何在大家的我的项目中实现它们。

~ 完,我是刷碗智,我要去刷碗了,骨的白。


代码部署后可能存在的 BUG 没法实时晓得,预先为了解决这些 BUG,花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

原文:https://learnvue.co/2020/12/h…

交换

文章每周继续更新,能够微信搜寻「大迁世界」第一工夫浏览和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 曾经收录,整顿了很多我的文档,欢送 Star 和欠缺,大家面试能够参照考点温习,另外关注公众号,后盾回复 福利,即可看到福利,你懂的。

退出移动版