Svelte教程翻译(三、逻辑渲染)

条件渲染

HTML没有表达逻辑的方式,比如条件和循环,Svelte有。

为了有条件地呈现某些内容,我们将其包装在if块中:

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

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

完整代码如下:

<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}
复制代码

点击按钮,按钮将在【Log out】与【Log in】之间切换。

因为有两个条件:if user.loggetinif!Loggetin,它们是互斥的,我们可以通过使用else块来简化这个组件:

{#if user.loggedIn}
	<button on:click={toggle}>
		Log out
	</button>
{:else}
	<button on:click={toggle}>
		Log in
	</button>
{/if}
复制代码

#字符总是表示块开始标记。/字符总是表示块结束标记。:字符,如{:else} ,表示块继续标记。别担心,你已经学会了几乎所有Svelte新增加到HTML中的语法。

完整代码如下:

<script>
	let user = { loggedIn: false };

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

{#if user.loggedIn}
	<button on:click={toggle}>
		Log out
	</button>
{:else}
	<button on:click={toggle}>
		Log in
	</button>
{/if}
复制代码

噢,忘记了,还有多条件的情况:

<script>
	let x = 7;
</script>

{#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块:

<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]

你可以使用第二个参数作为当前遍历对象的索引变量,如下所示:

{#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}
复制代码

如果您愿意,可以使用解构方式each cats as {id,name},这样可以用idname替换cat.idcat.name

完整代码如下:

<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>
复制代码

key的作用及使用

用话术描述有点吃力,看例子:

image-20210624160215738

下面,让我们点击【Remove first thing】按钮,这里,你要知道,删除第一行,你想要得到怎样的结果:

image-20210624160334482

噢,NO!!!这不是我想要的,我想这也不是你想要的结果,banana怎么会是苹果?

如何处理?

这时key登场了。

没有key的代码:

<button on:click={handleClick}>
	Remove first thing
</button>

{#each things as thing}
	<Thing name={thing.name}/>
{/each}
复制代码

增加key的代码:

<button on:click={handleClick}>
	Remove first thing
</button>

{#each things as thing (thing.id) }
	<Thing name={thing.name}/>
{/each}
复制代码

看出差别了么?这里,thing.id是密钥,它告诉Svelte如何在组件更新时确定要更改哪个DOM节点。

您可以使用任何对象作为键,因为Svelte在内部使用Map。换句话说,您可以使用thing而不是thing.id。但是,使用字符串或数字通常更安全,因为这意味着标识不会引用等式,例如,当使用来自API服务器的新数据进行更新时。

完整代码如下:

文件App.sevlte

<script>
	import Thing from './Thing.svelte';

	let things = [
		{ id: 1, name: 'apple' },
		{ id: 2, name: 'banana' },
		{ id: 3, name: 'carrot' },
		{ id: 4, name: 'doughnut' },
		{ id: 5, name: 'egg' },
	];

	function handleClick() {
		things = things.slice(1);
	}
</script>

<button on:click={handleClick}>
	Remove first thing
</button>

{#each things as thing (thing.id) }
	<Thing name={thing.name}/>
{/each}
复制代码

文件Thing.sevlte

<script>
	const emojis = {
        apple: "?",
        banana: "?",
        carrot: "?",
        doughnut: "?",
        egg: "?"
	}

	// the name is updated whenever the prop value changes...
	export let name;

	// ...but the "emoji" variable is fixed upon initialisation of the component
	const emoji = emojis[name];
</script>

<p>
	<span>The emoji for { name } is { emoji }</span>
</p>

<style>
	p {
		margin: 0.8em 0;
	}
	span {
		display: inline-block;
		padding: 0.2em 1em 0.3em;
		text-align: center;
		border-radius: 0.2em;
		background-color: #FFDFD3;
	}
</style>
复制代码

异步渲染

看文档时,当看到这个地方的时候,我眼前一亮,下面来介绍一下Sevlte中,给HTML增加的异步渲染功能块。

大多数web应用程序在某些时候必须处理异步数据。可以很容易地在你的标记中等待数据返回:

{#await promise}
	<p>...waiting</p>
{:then number}
	<p>The number is {number}</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}
复制代码

只考虑最新的promise,这意味着您不需要担心时序问题。

如果你知道你的promise不会被拒绝,你可以省略catch块。如果你不想显示任何内容,你也可以省略第一块,直到promise结束:

{#await promise then value}
	<p>the value is {value}</p>
{/await}
复制代码

完整的代码如下:

<script>
	async function getRandomNumber() {
		const res = await fetch(`tutorial/random-number`);
		const text = await res.text();

		if (res.ok) {
			return text;
		} else {
			throw new Error(text);
		}
	}
	
	let promise = getRandomNumber();

	function handleClick() {
		promise = getRandomNumber();
	}
</script>

<button on:click={handleClick}>
	generate random number
</button>

{#await promise}
	<p>...waiting</p>
{:then number}
	<p>The number is {number}</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}
复制代码

运行结果:

image-20210624161849629

image-20210624161910270

或者

image-20210624161959885

如果你觉得看得不过瘾,想亲手试试,可以前往官方网站在线体验一下:await-blocks

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享