组件规范
组件是Svelte应用的构建块。它们被写在.svelte文件,使用一个HTML超集。
脚本、样式和标识这三个部分都是可选的。
<script>
// logic goes here
</script>
<style>
/* styles go here */
</style>
<!-- markup (zero or more items) goes here -->
<script>
当一个组件创建后,script块包含着运行的javascript代码,在顶层声明(或导入)的变量在组件的标识中是“可见”的,
另外还有四条规则:
1、export创造一个组件道具
Svelte使用export关键字将变量声明标记为属性或道具,这意味着组件的用户可以访问它。
<script>
export let foo;
// Values that are passed in as props
// are immediately available
console.log({ foo });
</script>
可以为道具指定默认初始值。如果组件的使用者在实例化组件时未指定组件上的属性(或其初始值未定义),则将使用该属性。
请注意,每当使用者移除道具时,道具的值将设置为未定义,而不是初始值。
<script>
export let bar = 'optional default initial value';
export let baz = undefined;
</script>
在开发模式下,如果未提供默认初始值,并且使用者未指定值,则将打印警告。要消除此警告,请确保指定了默认初始值,即使未定义该值。
如果导出常量、类或函数,则它是从组件外部只读的。但是,函数表达式是有效的道具。
<script>
// these are readonly
export const thisIs = 'readonly';
export function greet(name) {
alert(`hello ${name}!`);
}
// this is a prop
export let format = n => n.toFixed(2);
</script>
您可以使用保留字作为道具名称。
<script>
let className;
// creates a `class` property, even
// though it is a reserved word
export { className as class };
</script>
2、任务是反应式的
要更改组件状态并触发重新呈现,只需分配给本地声明的变量。
更新表达式(count+=1)和属性赋值(obj.x=y)具有相同的效果。
因为Svelte的反应性是基于赋值的,所以使用.push()和.splice()这样的数组方法不会自动触发更新。
可以在tutorial中找到解决此问题的选项。
<script>
let count = 0;
function handleClick () {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
3、$:将语句标记为反应语句
任何顶级语句(即不在块或函数内)都可以通过在其前面加上$:JS标签语法来进行响应。响应语句在组件更新之前立即运行,只要它们所依赖的值发生更改。
<script>
export let title;
// this will update `document.title` whenever
// the `title` prop changes
$: document.title = title;
$: {
console.log(`multiple statements can be combined`);
console.log(`the current title is ${title}`);
}
</script>
如果语句完全由对未声明变量的赋值组成,Svelte将代表您插入let声明。
<script>
export let num;
// we don't need to declare `squared` and `cubed`
// — Svelte does it for us
$: squared = num * num;
$: cubed = squared * num;
</script>
4、使用$前缀存储以访问其值
存储是一个对象,它允许通过一个简单的存储契约对一个值进行被动访问。svelte/store模块包含满足此契约的最小存储实现。
任何时候,只要有对存储的引用,就可以通过在组件中以$字符作为前缀来访问它的值。这将导致Svelte声明前缀变量,并设置将在适当时取消订阅的存储订阅。
对$前缀变量的赋值要求变量是可写存储,并将导致调用存储的.set方法。
请注意,必须在组件的顶层声明存储,例如,不能在if块或函数内部声明。
局部变量(不代表存储值)不能有$前缀。
<script>
import { writable } from 'svelte/store';
const count = writable(0);
console.log($count); // logs 0
count.set(1);
console.log($count); // logs 1
$count = 2;
console.log($count); // logs 2
</script>
存储协议
store = {subscribe: (subscription: (value: any) => void) => () => void, set?: (value: any) => void }
您可以创建自己的存储区,而不依赖于svelte/store,通过执行存储协议:
1、存储区必须包含```.subscribe```方法,该方法必须接受订阅函数作为其参数。
调用```.subscribe```时,必须立即同步调用此订阅函数和存储的当前值。
每当存储的值更改时,必须稍后同步调用存储的所有活动订阅函数。
2、```.subscribe```方法必须返回unsubscribe函数。
调用unsubscribe函数必须停止其订阅,
并且存储区不得再次调用其相应的订阅函数。
3、存储可以选择性地包含```.set```方法,该方法必须接受存储的新值作为其参数,
并同步调用存储的所有活动订阅函数。这样的存储称为可写存储。
对于与RxJS observates的互操作性,还允许.subscribe方法返回带有.unsubscribe方法的对象,而不是直接返回unsubscribe函数。不过,请注意,除非.subscribe同步调用订阅(这不是observate规范所要求的),否则在调用之前,Svelte会将存储的值视为未定义。