Skip to main content

$props

组件的输入称为 props,是属性的缩写。你将 props 传递给组件就像你将属性传递给元素一样:

¥The inputs to a component are referred to as props, which is short for properties. You pass props to components just like you pass attributes to elements:

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 符文接收属性……

¥On the other side, inside MyComponent.svelte, we can receive props with the $props rune...

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>

...但是更常见的是,你会 destructure 你的 props:

¥...though more commonly, you’ll destructure your 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>

后备值(Fallback values)

¥Fallback values

解构允许我们声明后备值,如果父组件未设置给定的 prop,则使用这些值:

¥Destructuring allows us to declare fallback values, which are used if the parent component does not set a given prop:

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

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
();

后备值不会变成反应状态代理(有关更多信息,请参阅 更新属性

¥[!NOTE] Fallback values are not turned into reactive state proxies (see Updating props for more info)

重命名 props(Renaming props)

¥Renaming props

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

¥We can also use the destructuring assignment to rename props, which is necessary if they’re invalid identifiers, or a JavaScript keyword like super:

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

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 属性(Rest props)

¥Rest props

最后,我们可以使用 rest 属性来获取其余的 props:

¥Finally, we can use a rest property to get, well, the rest of the props:

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

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
();

更新属性(Updating props)

¥Updating props

当 prop 本身更新时,对组件内部 prop 的引用也会更新 - 当 countApp.svelte 中更改时,它也会在 Child.svelte 中更改。但子组件能够暂时覆盖 prop 值,这对于未保存的短暂状态(demo)很有用:

¥References to a prop inside a component update when the prop itself updates — when count changes in App.svelte, it will also change inside Child.svelte. But the child component is able to temporarily override the prop value, which can be useful for unsaved ephemeral state (demo):

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>

虽然你可以暂时重新分配属性,但除非它们是 bindable,否则你不应该改变属性。

¥While you can temporarily reassign props, you should not mutate props unless they are bindable.

如果 prop 是常规对象,则突变不会产生任何影响(demo):

¥If the prop is a regular object, the mutation will have no effect (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>

但是,如果 prop 是反应状态代理,则突变会产生影响,但你会看到 ownership_invalid_mutation 警告,因为组件正在改变不会 ‘belong’ 的状态(demo):

¥If the prop is a reactive state proxy, however, then mutations will have an effect but you will see an ownership_invalid_mutation warning, because the component is mutating state that does not ‘belong’ to it (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 声明的 prop 的 fallback 值保持不变 — 它不会变成反应状态代理 — 这意味着突变不会导致更新(demo

¥The fallback value of a prop not declared with $bindable is left untouched — it is not turned into a reactive state proxy — meaning mutations will not cause updates (demo)

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 来传达更改,或者 - 如果父级和子级应该共享同一个对象 - 使用 $bindable 符文。

¥In summary: don’t mutate props. Either use callback props to communicate changes, or — if parent and child should share the same object — use the $bindable rune.

类型安全(Type safety)

¥Type safety

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

¥You can add type safety to your components by annotating your props, as you would with any other variable declaration. In TypeScript that might look like this...

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

...而在 JSDoc 中你可以这样做:

¥...while in JSDoc you can do this:

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

当然,你可以将类型声明与注释分开:

¥You can, of course, separate the type declaration from the annotation:

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

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

svelte/elements 模块中提供了原生 DOM 元素的接口(参见 键入封装器组件

¥[!NOTE] Interfaces for native DOM elements are provided in the svelte/elements module (see Typing wrapper components)

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

¥Adding types is recommended, as it ensures that people using your component can easily discover which props they should provide.

上一页 下一页