Svelte 官方入门教程(4) - 模板逻辑

svelte cover

前两讲所探讨的关于组件的状态(反应性)以及组件向子组件传递参数,今天要进入模板逻辑

大家知道,HTML 没有表达逻辑的方法,比如条件和循环。 Svelte是可以的。

一、if块

为了有条件地渲染一些标记,我们将它包装在一个 if 块中:

1
2
3
4
5
6
7
8
9
10
11
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}

{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}

上面看着是不是以前使用过?在双向绑定之前的一段时间内,大家都是使用js的模板库来实现UI的渲染,它十分接近一些以往非常流行的 Handlebars 或者 Mustache 模板语言。

试试看——更新组件,然后点击按钮。

完整的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
let user = { loggedIn: false };

function toggle() {
user.loggedIn = !user.loggedIn;
}
</script>

{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}

{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}

二、Else 块

还是上面的例子,由于这两个条件 - if user.logged In 和 if !user.logged In - 是互斥的,我们可以通过使用 else 块来稍微简化这个组件:

1
2
3
4
5
6
7
8
9
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{:else}
<button on:click={toggle}>
Log in
</button>
{/if}

# 字符代表 块开始 标记。/字符代表 块结束 标记。而 {:else} 中的 : 字符,则表示 块连续 标记。不用担心,至此你几乎已经学完 SvelteHTML 添加的所有语法了。

三、Else-If 块

看下面的例子,可以使用else if将多个条件 “连接” 在一起:

1
2
3
4
5
6
7
{#if x > 10}
<p>{x} is greater than 10</p>
{:else if 5 > x}
<p>{x} is less than 5</p>
{:else}
<p>{x} is between 5 and 10</p>
{/if}

四、each 块

如果您需要遍历数据列表,请使用 each 块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>

<h1>The Famous Cats of YouTube</h1>
<ul>
{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}
</ul>

表达式 cats是一个数组,遇到数组或类似于数组的对象 (即具有length 属性)。你都可以通过 each […iterable]遍历迭代该对象。

你也可以将index 作为第二个参数(key),类似于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>

<h1>The Famous Cats of YouTube</h1>

<ul>
{#each cats as cat, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{i + 1}: {cat.name}
</a></li>
{/each}
</ul>

只要你愿意,还可以使用解构语法each cats as { id, name }, i,也即是用idname来代替cat.idcat.name

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>

<h1>The Famous Cats of YouTube</h1>

<ul>
{#each cats as { id, name }, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={id}">
{i + 1}: {name}
</a></li>
{/each}
</ul>

REPL

五、拥有key的each块

默认情况下,当您修改 each 块的值时,它将在块的末尾添加和删除项目,并更新任何已更改的值。 不过那可能不是你想要的。

说明原因比解释更容易。 单击“删除第一件事”按钮几次,注意会发生什么:它不会删除第一个 <Thing> 组件,而是删除最后一个 DOM 节点。 然后它会更新剩余 DOM 节点中的名称值,但不会更新表情符号。

还是看实例吧,不然光看文字描述会有点懵。

相反,我们只想删除第一个 <Thing> 组件及其 DOM 节点,而其他不受影响。

为此,我们为每个块指定一个唯一标识符(“key”)

1
2
3
{#each things as thing (thing.id)}
<Thing name={thing.name}/>
{/each}

这个 (thing.id) 告知 Svelte 如何计算变化的地方。

你可以将任何对象用作 key 来使用,就像Svelte 用 Map 在内部作为key一样,换句话说,你可以用 (thing) 来代替 (thing.id)作为 key 值。但是,使用字符串或者数字作为 key 值通常更安全,因为这能确保它的唯一性,例如,使用来自API服务器的新数据进行更新时。

如果熟悉Vue互助angular的会对这个感到熟悉,思路相似,或者说站在巨人的肩上。

六、await 块

很多Web应用程序都可能在某个时候有需要处理异步数据的需求。使用 Svelte 在标签中使用 await 处理 promises 数据亦是十分容易:

1
2
3
4
5
6
7
{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}

promise总是获取最新的信息,这使得你无需关心 rece 状态。

如果你的知道你的 promise 返回错误,则可以忽略 catch 块。如果在请求完成之前不想程序执行任何操作,也可以忽略第一个块。

1
2
3
{#await promise then value}
<p>the value is {value}</p>
{/await}

REPL

七、key 块

Key 块在表达式的值更改时销毁并重新创建其内容。如果您希望元素在值更改时播放其过渡,这很有用。

语法

1
2
3
{#key value}
<div transition:fade>{value}</div>
{/key}

如果key包裹着组件使用,将导致组件被重新实例化和重新初始化。

1
2
3
{#key value}
<Component />
{/key}

按照对key块的描述我们使用一个交互实例来看

REPL

上面使用if块和key块进行了对比,通过点击按钮观察,只有if块只有第一次的数字改变会有fly动画效果,后面都不在有,而key块则一致有效果。这说明只要 num 的值改变了,key 块内的元素都会被销毁且重新渲染。

总结

本讲把所有的模板逻辑的都讲了一遍,内容有点多,实际使用最多的是if块和each块。

如果你习惯了react的jsx或者Vue的模板语法,会觉得这个感觉好奇怪,不过你完全有可能一开始不太适应这种模板语言,甚至是非常别扭。

你学习了这些让你知道都有哪些可以使用的,实际中你可以使用插件来辅助你,这里推荐vscode 插件Svelte 3 Snippets

Svelte 3 Snippets

当然这个插件肯定不是包含所有的模板和其他的api,新的api加入插件的更新会延迟。


Svelte 官方入门教程(4) - 模板逻辑
http://yoursite.com/2022/07/11/svelte-tutorial-4/
作者
昂藏君子
发布于
2022年7月11日
许可协议