什么是生命周期
每个组件都有一个生命周期,从创建时开始,到销毁时结束。有一些函数可以让你在生命周期的关键时刻运行代码。
我们可以挂钩这些事件来帮助我们实现我们想要的功能。
首先我们会接触到四个必备的Hook:
- onMount 组件渲染后触发
- onDestroy 组件销毁后触发
- beforeUpdate 在 DOM 更新之前触发
- afterUpdateDOM 更新后触发
onMount
onMount 在组件第一次渲染到 DOM 之后运行,当我们需要在渲染后与元素进行交互时。
一个常见的场景就是提供 onMount 从其他来源获取数据,例如我们在 SSR 的情况下需要将 fetch 加载放到 onMount 之中,生命周期函数不会在 SSR 期间运行,这意味着我们可以避免获取应该在组件安装到 DOM 后延迟加载的数据。
下面我们来看一个案例:
<script> import { onMount } from 'svelte' let logoBase64 onMount(async () => { const response = await fetch('https://ucc.alicdn.com/images/user-upload-01/b474b1a7496a4c7cb5d9d3abef2c39d0.png') let logoBlob = await response.blob() const reader = new FileReader() reader.readAsDataURL(logoBlob) reader.onload = function () { logoBase64 = reader.result } }) </script> <img src={logoBase64} width="300px" alt="svelte logo">
onDestroy
onDestroy 允许我们清理数据或停止我们可能在组件初始化时开始的任何操作,例如使用 setInterval ,这样做可以防止内存泄漏。
需要特别注意的一件事是,如果我们在 onMount 函数中写 return ,它的功能与 onDestroy 一样!在组件被销毁时运行
<script> import { onMount } from 'svelte' onMount(async () => { const interval = setInterval(() => { console.log('hey, 我是uiuing!') }, 1000) return () => { clearInterval(interval) } }) </script>
和
<script> import { onDestroy } from 'svelte' const interval = setInterval(() => { console.log('hey, 我是uiuing!') }, 1000) onDestroy(() => { clearInterval(interval) }) </script>
相同!
beforeUpdate 和 afterUpdate
从函数名称中就可以看出来,他们两个是相关的。
那么具体在于:
beforeUpdate 函数在 DOM 更新之前触发。
afterUpdate 函数在 DOM 更新之后触发。
这个具体就要看使用场景了,不过这里需要注意,在组件初始化过程中,beforeUpdate 的触发比 onMount 触发更早,也就是在挂载DOM之前,beforeUpdate 同样会触发。
<script> import { afterUpdate, beforeUpdate, onMount } from 'svelte' onMount(() => { console.log('mounted') }) beforeUpdate(()=>{ console.log('beforeUpdate') }) afterUpdate(()=>{ console.log('afterUpdate') }) </script>
tick
tick 函数就比较特殊了,和其它的生命周期函数不同,可以随时调用它,而不仅仅是在组件首次初始化时调用。
这个函数返回一个 promise 并在 DOM 与数据同步后立即执行。
来看一个案例:
<script> import { tick } from "svelte"; let count = 0 let t async function handleUpdate() { count++ // await tick(); console.log(t.textContent); } </script> <div bind:this={t}> {count} </div> <button on:click={handleUpdate}> Count ++ </button>
这时候我们可以看到func触发的时候,其实DOM还没更新数据。
那么这时候我们就可以使用 tick() 函数,每当组件等待状态变化便会立即体现到DOM中 (除非没有等待状态变化),我们可以在上面的代码把注释取消掉。
这时候就同步了,当然我们也可以这样使用
<script> import { tick } from 'svelte' let count = 0 let t function handleUpdate() { count++ tick().then(() => { console.log(t.textContent) }) } </script>
这样是相同的。