Svelte中的Reactivity(响应式)和组件中的Props(属性)
时间:2021-03-22 01:43:55
Reactivity(响应式)
在Svelte
中响应式很简单,只需要定义一个变量,它就是响应式的,如果导出的是const
、class
、function
,则在组件之外是只读的。如:记录点击按钮的次数
。
<script>
let count = 0;
const onClick = () => count++;
</script>
<button on:click={onClick}>点击了{count}次</button>
注意:如果变量是
数组
,通过下标改变后,需要将新数组重新赋值给变量,否则视图不会更新。如果是对象且将其赋值给一个不是响应式的变量,则在更改了新变量的值之后需要将新变量重新赋值给对象,否则视图不会更新。
<script>
let user = {
github: 'https://github.com/sveltejs',
auth: {
qq: '123456'
}
};
let tags = ['code', 'blog', 'book'];
function onChangeGithub() {
// // 此处是值赋值,不是引用赋值,所以改变tmp需要再次赋值给user
// let tmp = user
// tmp.github = 'https://github.com/renzp94'
// user = tmp
user.github = 'https://github.com/renzp94';
}
function onChangeQQ() {
// 这个和改变github一样,需要将auth重新赋值给user.auth
let auth = user.auth;
auth.qq = '456789';
user.auth = auth;
}
function onChangeTag() {
// tags.push('svelte')
// // 只push,是不会视图是不会更新的,需要重新赋值
// tags = tags
// 这种更简洁
tags = [...tags, 'svelte'];
}
</script>
<div class="user">
<div>
<a href={user.github}>{user.github}</a>
</div>
<div>
QQ:{user.auth.qq}
</div>
<ul>
{#each tags as tag (tag)}
<li>{tag}</li>
{/each}
</ul>
<button on:click={onChangeGithub}>改变Github地址</button>
<button on:click={onChangeQQ}>改变QQ</button>
<button on:click={onChangeTag}>改变Tag</button>
</div>
{#each} ... {/each}
这是循环渲染的语法,下篇文章会介绍,这里先不用管。
在Svelte
中如果需要根据某个值来动态计算得到某个结果,并且值每次改变后,都会重新计算,那就需要用到$:
(reactive declarations(响应式声明)),如果语句是给未声明的变量赋值组成,则会自动用let
声明那个未声明的变量,如:通过姓和名得到全名
。
<script>
let firstname = '';
let lastname = '';
// 未声明fullname,则自动声明
$: fullname = `${firstname}${lastname}`;
</script>
<label>
姓氏:
<input type="text" placeholder="请输入姓氏" bind:value={firstname} />
</label>
<label>
名称:
<input type="text" placeholder="请输入名称" bind:value={lastname} />
</label>
<div>您的全名是:{fullname}</div>
上述例子只是一个简单的使用,如果需要一些判断或处理得到结果的话,可以使用$:{}
。将上述例子完善一下,做一些校验。
<script>
let firstname = '';
let lastname = '';
let fullname = '';
let error = '';
$: {
if (!firstname) {
error = '请输入姓氏';
} else if (!lastname) {
error = '请输入名称';
} else {
error = '';
fullname = `${firstname}${lastname}`;
}
}
</script>
<div class="error">
{error}
</div>
<label>
姓氏:
<input type="text" placeholder="请输入姓氏" bind:value={firstname} />
</label>
<label>
名称:
<input type="text" placeholder="请输入名称" bind:value={lastname} />
</label>
{#if fullname}
<div>您的全名是:{fullname}</div>
{/if}
<style>
.error {
color: red;
}
</style>
Props(组件属性)
一般封装组件,都需要对外提供一些属性来支持自定义组件,在Svelte
中组件可通过export
来对外暴露属性。
- 若需要指定
prop
的默认值,直接在定义时设置默认值即可。 - 如果有一个属性对象,可以通过
对象解构
的方式直接赋值给组件。 - 在组件内可以通过
$$props
来访问所有属性(包括未通过export
导出的),可通过$$restProps
仅访问未使用export
导出的属性。
Hello.svelte
<script>
export let msg = 'world';
export let desc;
console.log($$props);
console.log($$restProps);
</script>
<div>Hello {msg}</div>
{#if desc}
<div>{desc}</div>
{/if}
App.svelte
<script>
import Hello from './Hello.svelte';
const obj = {
msg: 'CodeBook',
desc: '有质感的编程'
};
</script>
<Hello c="ccc" />
<Hello msg="svelte" />
<Hello {...obj} />
{#if} ... {/if}
这是条件渲染的语法,下篇文章会介绍,这里先不用管。
最后提一句,如果想让组件外部设置组件的 class 属性,需要export
,但是class
是关键字,不能export
,所以需要转换一下思路,通过一下方式实现。
<script>
export let className;
export { className as class };
</script>