Skip to main content

$props

组件的输入被称为props,这是properties的简称。您向组件传递 props 的方式就像向元素传递属性一样:

App
<script>
	import MyComponent from './MyComponent.svelte';
</script>

<MyComponent adjective="cool" />
<script lang="ts">
	import MyComponent from './MyComponent.svelte';
</script>

<MyComponent adjective="cool" />

在另一方面,在MyComponent.svelte内部,我们可以通过$props属性接收 props...

MyComponent
<script>
	let props = $props();
</script>

<p>this component is {props.adjective}</p>
<script lang="ts">
	let props = $props();
</script>

<p>this component is {props.adjective}</p>

...尽管更常见的是,你会解构你的 props:

MyComponent
<script>
	let { adjective } = $props();
</script>

<p>this component is {adjective}</p>
<script lang="ts">
	let { adjective } = $props();
</script>

<p>this component is {adjective}</p>

回退值

解构允许我们声明回退值,这些值在父组件未设置给定属性(或值是 undefined)时使用:

let { let adjective: anyadjective = 'happy' } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

[!注意] 回退值不会被转换为响应式状态代理(有关更多信息,请参阅更新属性

重命名属性

我们还可以使用解构赋值来重命名 props,这在它们是无效标识符或 JavaScript 关键字(如super)时是必要的:

let { super: let trouper: anytrouper = 'lights are gonna find me' } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

Rest props

最后,我们可以使用一个 剩余属性 来获取,嗯,其余的 props:

let { let a: anya, let b: anyb, let c: anyc, ...let others: anyothers } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

更新属性

组件内部属性更新时对属性的引用也会更新——当 countApp.svelte 中变化时,它也会在 Child.svelte 中变化。但子组件可以临时覆盖属性值,这在处理未保存的短暂状态时可能很有用(演示)。

App
<script>
	import Child from './Child.svelte';

	let count = $state(0);
</script>

<button onclick={() => (count += 1)}>
	clicks (parent): {count}
</button>

<Child {count} />
<script lang="ts">
	import Child from './Child.svelte';

	let count = $state(0);
</script>

<button onclick={() => (count += 1)}>
	clicks (parent): {count}
</button>

<Child {count} />
Child
<script>
	let { count } = $props();
</script>

<button onclick={() => (count += 1)}>
	clicks (child): {count}
</button>
<script lang="ts">
	let { count } = $props();
</script>

<button onclick={() => (count += 1)}>
	clicks (child): {count}
</button>

虽然您可以临时重新分配属性,但除非它们是可绑定的,否则您不应该修改属性。

如果属性是一个普通对象,则变异将没有效果(demo):

App
<script>
	import Child from './Child.svelte';
</script>

<Child object={{ count: 0 }} />
<script lang="ts">
	import Child from './Child.svelte';
</script>

<Child object={{ count: 0 }} />
Child
<script>
	let { object } = $props();
</script>

<button onclick={() => {
	// has no effect
	object.count += 1
}}>
	clicks: {object.count}
</button>
<script lang="ts">
	let { object } = $props();
</script>

<button onclick={() => {
	// has no effect
	object.count += 1
}}>
	clicks: {object.count}
</button>

如果属性是一个响应式状态代理,那么突变产生影响,但你会看到一个ownership_invalid_mutation警告,因为组件正在修改不属于它的状态(demo):

App
<script>
	import Child from './Child.svelte';

	let object = $state({count: 0});
</script>

<Child {object} />
<script lang="ts">
	import Child from './Child.svelte';

	let object = $state({count: 0});
</script>

<Child {object} />
Child
<script>
	let { object } = $props();
</script>

<button onclick={() => {
	// will cause the count below to update,
	// but with a warning. Don't mutate
	// objects you don't own!
	object.count += 1
}}>
	clicks: {object.count}
</button>
<script lang="ts">
	let { object } = $props();
</script>

<button onclick={() => {
	// will cause the count below to update,
	// but with a warning. Don't mutate
	// objects you don't own!
	object.count += 1
}}>
	clicks: {object.count}
</button>

备用值的属性未使用$bindable声明时保持不变——它不会被转换为响应式状态代理——这意味着变更不会引起更新(示例

Child
<script>
	let { object = { count: 0 } } = $props();
</script>

<button onclick={() => {
	// has no effect if the fallback value is used
	object.count += 1
}}>
	clicks: {object.count}
</button>
<script lang="ts">
	let { object = { count: 0 } } = $props();
</script>

<button onclick={() => {
	// has no effect if the fallback value is used
	object.count += 1
}}>
	clicks: {object.count}
</button>

总结:不要修改 props。要么使用回调 props 来传递变化,或者——如果父元素和子元素应该共享同一个对象——使用$bindable rune。

类型安全

您可以通过注释您的 props 来为组件添加类型安全,就像您对任何其他变量声明一样。在 TypeScript 中,这可能看起来像这样...

<script lang="ts">
	let { adjective }: { adjective: string } = $props();
</script>

...當在 JSDoc 中可以這樣做:

<script>
	/** @type {{ adjective: string }} */
	let { adjective } = $props();
</script>

当然,您可以将类型声明与注解分开:

<script lang="ts">
	interface Props {
		adjective: string;
	}

	let { adjective }: Props = $props();
</script>

[!注意] 本地 DOM 元素的接口在svelte/elements模块中提供(见类型包装组件

添加类型是推荐的,因为它确保使用您组件的人可以轻松地发现他们应该提供哪些属性。

$props.id()

此符文自 5.20.0 版本添加,生成一个仅对当前组件实例唯一的 ID。在服务器端渲染的组件中,该值将在服务器和客户端之间保持一致。

这对于通过属性如foraria-labelledby链接元素很有用。

<script>
	const uid = $props.id();
</script>

<form>
	<label for="{uid}-firstname">First Name: </label>
	<input id="{uid}-firstname" type="text" />

	<label for="{uid}-lastname">Last Name: </label>
	<input id="{uid}-lastname" type="text" />
</form>

Edit this page on GitHub llms.txt

previous next