tick
関数は他のライフサイクル関数とは異なり、コンポーネントが最初に初期化されたときだけでなく、いつでも呼び出すことができます。この関数は、保留中の状態変更が DOM に適用されるとすぐに (保留中の状態変更がない場合はすぐに) resolve する promise を返します。
Svelte でコンポーネントの状態を更新しても、すぐに DOM を更新するわけではありません。その代わりに、次の マイクロタスク まで待って、他のコンポーネントも含めて適用する必要のある変更があるかどうかを確認します。そうすることで不要な作業を回避し、ブラウザはより効果的にバッチ処理を行うことができます。
この例では、その動作を見ることができます。テキストの範囲を選択してタブキーを押します。<textarea>
の値が変更されるため、現在の選択範囲がクリアされ、カーソルが最後までジャンプしてしまいます。これは tick
をインポートすることで修正できます…
App.svelte
import { tick } from 'svelte';
let text = `Select some text and hit the tab key to toggle uppercase`;
…そして handleKeydown
の最後に this.selectationStart
と this.selectationEnd
を設定する直前に実行します。
App.svelte
await tick();
this.selectionStart = selectionStart;
this.selectionEnd = selectionEnd;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<script>
let text = `Select some text and hit the tab key to toggle uppercase`;
async function handleKeydown(event) {
if (event.key !== 'Tab') return;
event.preventDefault();
const { selectionStart, selectionEnd, value } = this;
const selection = value.slice(selectionStart, selectionEnd);
const replacement = /[a-z]/.test(selection)
? selection.toUpperCase()
: selection.toLowerCase();
text =
value.slice(0, selectionStart) +
replacement +
value.slice(selectionEnd);
// this has no effect, because the DOM hasn't updated yet
this.selectionStart = selectionStart;
this.selectionEnd = selectionEnd;
}
</script>
<textarea
value={text}
on:keydown={handleKeydown}
/>
<style>
textarea {
width: 100%;
height: 100%;
resize: none;
}
</style>