什么是生命周期
每个组件都有一个生命周期,从创建时开始,到销毁时结束。有一些函数可以让你在生命周期的关键时刻运行代码。
我们可以挂钩这些事件来帮助我们实现我们想要的功能。
首先我们会接触到四个必备的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://img-blog.csdnimg.cn/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>
这样是相同的。