Svelte官网学习——生命周期

283 阅读2分钟

onMount

官网地址

每个组件都有一个生命周期,它从创建时开始,在销毁时结束。有一些函数允许您在生命周期的关键时刻运行代码。

最常用的是onMount,它在组件首次呈现给DOM之后运行。我们之前在渲染元素时遇到过它。

<script>
    import { onMount } from 'svelte';
    let photos = [];
	
    onMount(async () => {
        const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`);
        photos = await res.json();
    })
</script>

<style>
    .photos {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(5, 1fr);
        grid-gap: 8px;
    }

    figure, img {
        width: 100%;
        margin: 0;
    }
</style>

<h1>Photo album</h1>

<div class="photos">
    {#each photos as photo}
        <figure>
            <img src={photo.thumbnailUrl} alt={photo.title}>
            <figcaption>{photo.title}</figcaption>
        </figure>
    {:else}
    <!-- this block renders when photos.length === 0 -->
    <p>loading...</p>
    {/each}
</div>

由于服务器端呈现(SSR)的原因,建议将获取放在onMount中,而不是放在

生命周期函数必须在组件初始化时被调用,这样回调函数就会绑定到组件实例上——而不是(比如说)在setTimeout中。

如果onMount回调函数返回一个函数,该函数将在组件销毁时被调用。

onDestroy

要在组件被销毁时运行代码,请使用onDestroy。

例如,我们可以在组件初始化时添加一个setInterval函数,并在它不再相关时清理它。这样做可以防止内存泄漏。

<script>
    import { onDestroy } from 'svelte';

    let seconds = 0;
    const interval = setInterval(() => seconds += 1)
	
    onDestroy(() => clearInterval(interval))
</script>

<p>
    The page has been open for
    {seconds} {seconds === 1 ? 'second' : 'seconds'}
</p>

虽然在组件初始化期间调用生命周期函数很重要,但从哪里调用它们并不重要。因此,如果我们愿意,我们可以将interval逻辑抽象为utils.js中的辅助函数…

import { onDestroy } from 'svelte';

export function onInterval(callback, milliseconds) {
    const interval = setInterval(callback, milliseconds);

    onDestroy(() => {
        clearInterval(interval);
    });
}

...然后将它导入到我们的组件中:

<script>
    import { onInterval } from './utils.js';

    let seconds = 0;
    onInterval(() => seconds += 1, 1000);
</script>

beforeUpdate & afterUpdate

顾名思义,beforeUpdate 函数实现在DOM渲染完成前执行。afterUpdate函数则相反,它会运行在你的异步数据加载完成后。

总之,它们对于一些需要以状态驱动的地方很有用, 例如渲染标签的滚动位置。

let div;
let autoscroll;

beforeUpdate(() => {
    autoscroll = div && (div.offsetHeight + div.scrollTop) > (div.scrollHeight - 20);
});

afterUpdate(() => {
    if (autoscroll) div.scrollTo(0, div.scrollHeight);
});

请注意,beforeUpdate将在组件挂载之前首先运行,因此我们需要在读取div属性之前检查它是否存在。

Tick

tick函数不同于其他生命周期函数,因为您可以在任何时候调用它,而不仅仅是在组件第一次初始化的时候。它返回一个承诺,只要将任何挂起状态更改应用到DOM(如果没有挂起状态更改,则立即解决),该承诺就会立即解决。 

 当你在Svelte中更新组件状态时,它不会立即更新DOM。相反,它会等待到下一个微任务,以查看是否需要应用任何其他更改,包括在其他组件中。这样做可以避免不必要的工作,并允许浏览器更有效地进行批处理。

您可以在本例中看到这种行为。选择一个文本范围并按tab键。因为值改变了,当前选择被清除,光标跳转到末尾。我们可以通过导入tick来解决这个问题……

import { tick } from 'svelte';

... 然后在设置之前立即运行它。selectionStart这。handleKeydown末尾的selectionEnd:

await tick();
this.selectionStart = selectionStart;
this.selectionEnd = selectionEnd;