$props
元件的輸入稱為 *props*,是 *properties* 的縮寫。您將 props 傳遞給元件,就像將屬性傳遞給元素一樣
<script>
import MyComponent from './MyComponent.svelte';
</script>
<MyComponent adjective="cool" />
另一方面,在 MyComponent.svelte
內部,我們可以使用 $props
符文接收 props...
<script>
let props = $props();
</script>
<p>this component is {props.adjective}</p>
...雖然更常見的做法是解構您的 props
<script>
let { adjective } = $props();
</script>
<p>this component is {adjective}</p>
預設值
解構允許我們宣告預設值,如果父元件未設定給定的 prop,則會使用這些值
let { let adjective: any
adjective = '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();
$props();
預設值不會轉換為反應式狀態代理(有關詳細資訊,請參閱更新 props)
重新命名 props
我們也可以使用解構賦值來重新命名 props,如果它們是無效的識別符號,或是像 super
這樣的 JavaScript 關鍵字,則這是必要的
let { super: let trouper: any
trouper = '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();
$props();
剩餘 props
最後,我們可以使用剩餘屬性來取得,嗯,其餘的 props
let { let a: any
a, let b: any
b, let c: any
c, ...let others: any
others } = function $props(): any
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$props();
更新 props
當 prop 本身更新時,元件內部的 prop 參考也會更新 — 當 App.svelte
中的 count
變更時,它也會在 Child.svelte
內部變更。但是子元件能夠暫時覆寫 prop 值,這對於未儲存的臨時狀態非常有用 (範例)
<script>
import Child from './Child.svelte';
let count = $state(0);
</script>
<button onclick={() => (count += 1)}>
clicks (parent): {count}
</button>
<Child {count} />
<script>
let { count } = $props();
</script>
<button onclick={() => (count += 1)}>
clicks (child): {count}
</button>
雖然您可以暫時重新賦值 props,但不應變更 props,除非它們是可綁定的。
如果 prop 是常規物件,則變更將不會產生任何效果 (範例)
<script>
import Child from './Child.svelte';
</script>
<Child object={{ count: 0 }} />
<script>
let { object } = $props();
</script>
<button onclick={() => {
// has no effect
object.count += 1
}}>
clicks: {object.count}
</button>
但是,如果 prop 是反應式狀態代理,則變更會產生效果,但您會看到ownership_invalid_mutation
警告,因為元件正在變更不「屬於」它的狀態 (範例)
<script>
import Child from './Child.svelte';
let object = $state({count: 0});
</script>
<Child {object} />
<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>
未使用 $bindable
宣告的 prop 的預設值保持不變 — 它不會轉換為反應式狀態代理 — 這表示變更不會導致更新 (範例)
<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>
總結:請勿變更 props。請使用回呼 props 來傳達變更,或者 — 如果父元件和子元件應共用同一個物件 — 請使用$bindable
符文。
類型安全
您可以像對待任何其他變數宣告一樣,透過註解您的 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>
建議新增類型,因為它可以確保使用您元件的人員可以輕鬆發現他們應該提供的 props。