Svelte中的动态渲染和事件绑定
时间:2021-03-22 06:30:46
动态渲染
在Svelte
中支持:条件渲染(if)
、列表渲染(each)
、异步判断渲染(await)
。
条件渲染(if)
在Svelte
中使用条件渲染主要有以下几个方式:
- if:
{#if 条件} ... {/if}
- if-else:
{#if 条件} ... {:else} ... {/if}
- if-else if:
{#if 条件} ... {:else if 条件} ... {/if}
<script>
let role = 'admin';
</script>
<select bind:value={role}>
<option value="normal">普通用户</option>
<option value="admin">管理员</option>
<option value="root">超级管理员</option>
</select>
{#if role === 'normal'}
<div>普通用户</div>
{:else if role === 'admin'}
<div>管理员</div>
{:else if role === 'root'}
<div>超级管理员</div>
{:else}
<div>未知身份</div>
{/if}
列表渲染(each)
在Svelte
中列表渲染通过{#each 列表 as 列表元素,列表下标 (key)} ... {/each}
,支持数组
或类似数组的对象(有length属性)
,列表元素支持解构。其中,key
是为了保证列表数据更新后视图渲染正确,一般需要具有唯一性。
<script>
const books = [
{ id: 1, text: 'Javascript' },
{ id: 2, text: 'Svelte' },
{ id: 3, text: 'React' },
{ id: 4, text: 'Vue' }
];
</script>
<ul>
<!--
{#each books as item,index (item.id)}
<li>{index + 1}. {item.text}</li>
{/each}
-->
{#each books as { id, text }, index (id)}
<li>{index + 1}. {text}</li>
{/each}
</ul>
异步判断渲染(await)
当列表需要请求中状态时,就可以用异步判断渲染
,主要有以下几个方式。
- 请求中、成功、错误:
{#await expression}...{:then data}...{:catch error}...{/await}
- 请求中、成功:
{#await expression}...{:then data}...{/await}
- 请求成功:
{#await expression then data}...{/await}
- 请求错误:
{#await expression catch error}...{/await}
<script>
let list = [];
function mock() {
return new Promise((resolve, reject) => {
const list = [
{ id: 1, text: 'Javascript' },
{ id: 2, text: 'Svelte' },
{ id: 3, text: 'React' },
{ id: 4, text: 'Vue' }
];
setTimeout(() => {
resolve(list);
// reject()
}, 3000);
});
}
async function init() {
const data = await mock();
list = data;
}
let promise = init();
</script>
{#await promise}
<span>loading...</span>
{:then}
<ul>
{#each list as { id, text } (id)}
<li>{text}</li>
{/each}
</ul>
{:catch}
<span>请求失败,请稍后重试</span>
{/await}
注意:如果不需要请求或失败后的数据可以省略为:
{:then data}
→{:then}
、{:catch error}
→{:catch}
事件绑定
DOM 事件绑定
在Svelte
中使用on:
来绑定事件,支持inline handlers(内联函数)
。
<script>
let count = 0;
const onClick = () => count++;
</script>
<!-- 内联样式 -->
<!-- <button on:click={() => count++}>点击了{count}次</button> -->
<button on:click={onClick}>点击了{count}次</button>
Svelte
同时也提供了可以更改其行为的事件修饰符,用|
使用,修饰符可以多个使用。
preventDefault
:event.preventDefault()
阻止默认事件stopPropagation
:event.stopPropagation()
阻止事件传递passive
:改善了触摸/滚轮事件的滚动性能(Svelte 会在安全的地方自动添加滚动条)nonpassive
:明确设置passive: false
capture
:将事件触发时机改为捕获阶段
,默认为冒泡阶段
。MDN Docsonce
:只触发一次self
:仅当event.target
是元素本身时才会触发事件
<script>
let count = 0;
let blockCount = 0;
const onClick = () => count++;
const onBlockClick = () => blockCount++;
</script>
<div class="block" on:click|self={onBlockClick}>
block被点击了{blockCount}次
<button on:click|once={onClick}>点击了{count}次</button>
</div>
<style>
.block {
background-color: red;
}
</style>
组件中传递事件
如果想监听组件的事件,则需要在组件内容触发事件,可通过createEventDispatcher
创建一个触发器来触发。
注意:通过
createEventDispatcher
触发的事件在回调中的参数是一个自定义事件对象CustomEvent
,需要通过e.detail
来获取触发时传入的数据。
Select.svelte
<script>
import { createEventDispatcher } from 'svelte';
export let value;
const dispatch = createEventDispatcher();
const onChange = () => dispatch('change', value);
</script>
<select bind:value on:blur on:change={onChange}>
<slot />
</select>
App.svelte
<script>
import Select from './Select.svelte';
let value = '1';
const onChange = (e) => {
console.log(e.detail);
};
</script>
<Select bind:value on:change={onChange}>
<option value="1">选项1</option>
<option value="2">选项2</option>
<option value="3">选项3</option>
</Select>
组件事件不会冒泡,若需要监听某个深度嵌套的组件,则需要在中间组件做转发,若中间组件只是转发事件,不对事件传递的数据做处理,则可以通过on:事件名
直接转发(DOM 元素也适用),无需通过createEventDispatcher
来触发。
Level2.svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
const onClick = () => dispatch('click', 'click');
</script>
<button on:click={onClick}>
<slot />
</button>
Level1.svelte
<script>
import { createEventDispatcher } from 'svelte';
import Level2 from './Level2.svelte';
const dispatch = createEventDispatcher();
const onClick = (e) => dispatch('click', `${e.detail} Level1处理了`);
</script>
<Level2>
Level1未做转发
<slot />
</Level2>
<Level2 on:click={onClick}>
Level1处理
<slot />
</Level2>
<Level2 on:click>
<slot />
</Level2>
App.svelte
<script>
import Level1 from './Level1.svelte';
const onClick = (e) => console.log(e.detail);
</script>
<Level1 on:click={onClick}>点击</Level1>