Svelte中的一些其他用法
Action
Action
可以针对元素级别的生命周期做一些自定义行为,主要提供三个生命周期:mounted
、update
、destroy
。
Action
是一个函数,有两个参数,第一个参数为元素,第二个参数为传入参数。函数主体为mounted
生命周期,其内部返回一个对象,对象可以包含两个属性分别为:update
,destroy
。mounted
会在元素渲染后执行,update
会在Action
参数发生变化后调用,destroy
会在元素销毁后调用。
countAction.js
export default (node, params) => {
console.log('mounted:', node, params);
return {
update(val) {
console.log('update:', val);
},
destroy() {
console.log('destroy');
}
};
};
App.svelte
<script>
import countAction from './countAction';
let count = 0;
const onAdd = () => count++;
</script>
<h1 use:countAction={count}>{count}</h1>
<button on:click={onAdd}> +1 </button>
Class
Svelte
中对于绑定class
提供了一些指令来简化。
class={条件?类名1:类名2}
:条件满足用类名1
,否则用类名2
class:类名={条件}
:条件满足则使用类名
class:类名
:变量名和类名一致,当类名为真时则采用类名。
<script>
let bold = true;
let error = true;
</script>
<div class={error ? 'red' : 'green'}>hello</div>
<div class:bold>Hello</div>
<div class:bold>Hello</div>
<style>
.bold {
font-weight: bold;
}
.red {
color: red;
}
.green {
color: green;
}
</style>
Context
当需要兄弟组件间共享数据时,可以通过Context
来操作。Context API
提供了三个方法:
setContext
:设置context
。接受两个参数:key
,value
。getContext
:获取context
。接受一个参数:key
。hasContext
:判断是否有某个context
。接受一个参数:key
。
Button.svelte
<script>
import { getContext, hasContext } from 'svelte';
let border = false;
console.log(hasContext('BUTTON_BORDER'), getContext('BUTTON_BORDER'));
if (hasContext('BUTTON_BORDER')) {
border = getContext('BUTTON_BORDER');
}
</script>
<button class:border>
<slot />
</button>
<style>
button {
border: none;
}
.border {
border: 1px solid #000;
}
</style>
App.svelte
<script>
import Button from './Button.svelte';
import { setContext } from 'svelte';
setContext('BUTTON_BORDER', true);
</script>
<Button>按钮</Button>
Component Slot
Svelte
还为组件提供了插槽,实现更灵活的自定义组件。使用插槽用<slot></slot>
,如果不指定name
则为默认插槽,指定了name
则为命名插槽
。如果需要给某个插槽指定默认内容,则在<slot>
和</slot>
之前添加默认内容即可,当插槽没有指定内容时会采用默认内容。在组件外使用插槽时,对于默认插槽只需要放在组件区域内,如:<Button>默认插槽</Button>
,对于命名插槽则需要使用slot="插槽名"
属性在组件区域内指定,如:<Button><span slot="suffix">命名插槽</span></Button>
。如果需要根据插槽是否存在来进行相应操作,还可以用$$slots
检查是否有某个插槽是否存在。如果需要插槽内可以访问子组件中才有的数据,可以使用slot props
,通过在组件内slot
上设置属性,并在父组件中使用组件时用let
指令使用。
Button.svelte
<script>
console.log('default: ', $$slots.defaults);
console.log('prefix: ', $$slots.prefix);
console.log('suffix: ', $$slots.suffix);
let hoving = false;
const onMouseenter = () => (hoving = true);
const onMouseleave = () => (hoving = false);
</script>
<button on:mouseenter={onMouseenter} on:mouseleave={onMouseleave}>
<slot name="prefix">默认的prefix</slot>
<slot {hoving} />
<slot name="suffix" />
</button>
App.svelte
<script>
import Button from './Button.svelte';
</script>
<Button let:hoving>
{#if hoving}
鼠标悬停
{:else}
默认内容
{/if}
<span slot="suffix">后置内容</span>
</Button>
内置元素
Svelte
提供了一些内置元素:
<svelte:self>
:允许组件递归的调用自己。<svelte:component>
:设置动态组件。<svelte:window>
:window
对象。<svelte:body>
:body
元素。<svelte:head>
:head
元素。<svelte:options>
:指定编译选项。immutable
:是否禁止使用可变数据accessors
:是否为组件的 props 添加getter
和setter
namespace
:命名空间tag
:将组件编译成自定义元素的名称
<svelte:fragment>
:在使用组件插槽配合使用可以不渲染元素。
Menu.svelte
<script>
export let menus;
</script>
<div>
<slot name="test" />
{#each menus as menu (menu.key)}
{#if menu.children && menu.children.length > 0}
<div>{menu.name}</div>
<div style="margin-left: 8px">
<svelte:self menus={menu.children} />
</div>
{:else}
<div>{menu.name}</div>
{/if}
{/each}
</div>
App.svelte
<script>
import Menu from './Menu.svelte';
let menus = [
{
key: 'home',
name: '首页'
},
{
key: 'user',
name: '用户管理',
children: [
{
key: 'admin',
name: '超级管理员'
},
{
key: 'normal',
name: '普通用户'
}
]
}
];
</script>
<Menu {menus}>
<svelte:fragment slot="test">
<div>test</div>
</svelte:fragment>
</Menu>
module context
Svelte
提供了<script context="module"></script>
块来执行模块首次加载时的代码,不是在组件实例化时运行(组件实例化运行时在<script></script>
块中)。
Button.svelte
<script context="module">
let buttonText = '';
</script>
<script>
export let text;
const onClick = () => {
console.log('button text before:', buttonText);
buttonText = text;
};
</script>
<button on:click={onClick}>
{text}
</button>
App.svelte
<script>
import Button from './Button.svelte';
</script>
<Button text="按钮1" />
<Button text="按钮2" />
<Button text="按钮3" />
<Button text="按钮4" />