$props
Входные данные компонента называются props, что является сокращением от properties. Вы передаете пропсы компонентам так же, как передаете атрибуты элементам:
<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…
<script> let props = $props();</script>
<p>этот компонент — {props.adjective}</p><script lang="ts"> let props = $props();</script>
<p>этот компонент — {props.adjective}</p>…хотя чаще всего вы будете деструктурировать ваши пропсы:
<script> let { adjective } = $props();</script>
<p>этот компонент — {adjective}</p><script lang="ts"> let { adjective } = $props();</script>
<p>этот компонент — {adjective}</p>Значения по умолчанию
Заголовок раздела «Значения по умолчанию»Деструктуризация позволяет нам объявлять значения по умолчанию, которые используются, если родительский компонент не устанавливает данный проп (или значение undefined):
let { adjective = 'happy' } = $props();Переименование пропсов
Заголовок раздела «Переименование пропсов»Мы также можем использовать деструктурирующее присваивание для переименования пропсов, что необходимо, если они являются недопустимыми идентификаторами или ключевым словом JavaScript, таким как super:
let { super: trouper = 'свет меня найдёт' } = $props();Остаточные пропсы
Заголовок раздела «Остаточные пропсы»Наконец, мы можем использовать остаточное свойство (rest property), чтобы получить все остальные, необъявленные, пропсы:
let { a, b, c, ...others } = $props();Обновление пропсов
Заголовок раздела «Обновление пропсов»Ссылки на проп внутри компонента обновляются, когда сам проп обновляется — когда count изменяется в App.svelte, он также изменится внутри Child.svelte. Однако дочерний компонент может временно переопределить значение пропа, что может быть полезно для несохранённого эфемерного состояния (демонстрация):
<script> import Child from './Child.svelte';
let count = $state(0);</script>
<button onclick={() => (count += 1)}> нажатий (parent): {count}</button>
<Child {count} /><script lang="ts"> import Child from './Child.svelte';
let count = $state(0);</script>
<button onclick={() => (count += 1)}> нажатий (parent): {count}</button>
<Child {count} /><script> let { count } = $props();</script>
<button onclick={() => (count += 1)}> нажатий (child): {count}</button><script lang="ts"> let { count } = $props();</script>
<button onclick={() => (count += 1)}> нажатий (child): {count}</button>Хотя вы можете временно переопределять пропсы, вы не должны их изменять, если они не являются привязываемыми.
Если проп является обычным объектом, изменение не окажет никакого эффекта (демонстрация):
<script> import Child from './Child.svelte';</script>
<Child object={{ count: 0 }} /><script lang="ts"> import Child from './Child.svelte';</script>
<Child object={{ count: 0 }} /><script> let { object } = $props();</script>
<button onclick={() => { // не имеет эффекта object.count += 1}}> нажатий: {object.count}</button><script lang="ts"> let { object } = $props();</script>
<button onclick={() => { // не имеет эффекта object.count += 1}}> нажатий: {object.count}</button>Однако, если проп является прокси реактивного состояния, то изменения будут иметь эффект, но вы увидите предупреждение ownership_invalid_mutation, потому что компонент изменяет состояние, которое ему не «принадлежит» (демонстрация):
<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} /><script> let { object } = $props();</script>
<button onclick={() => { // вызовет обновление счётчика ниже, // но с предупреждением. Не изменяйте // объекты, которые вам не принадлежат! object.count += 1}}> нажатий: {object.count}</button><script lang="ts"> let { object } = $props();</script>
<button onclick={() => { // вызовет обновление счётчика ниже, // но с предупреждением. Не изменяйте // объекты, которые вам не принадлежат! object.count += 1}}> нажатий: {object.count}</button>Стандартное значение пропа, не объявленного с помощью $bindable, остается нетронутым — оно не превращается в прокси реактивного состояния — что означает, что изменения не вызовут обновления (демонстрация)
<script> let { object = { count: 0 } } = $props();</script>
<button onclick={() => { // не имеет эффекта, если используется значение по умолчанию object.count += 1}}> нажатий: {object.count}</button><script lang="ts"> let { object = { count: 0 } } = $props();</script>
<button onclick={() => { // не имеет эффекта, если используется значение по умолчанию object.count += 1}}> нажатий: {object.count}</button>В заключение: не изменяйте пропсы. Либо используйте колбэк-пропсы для передачи изменений, либо — если родитель и потомок должны использовать один и тот же объект — используйте руну $bindable.
Безопасность типов
Заголовок раздела «Безопасность типов»Вы можете добавить безопасность типов к вашим компонентам, аннотируя ваши пропсы, как вы бы сделали с любым другим объявлением переменной. В 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.id()
Заголовок раздела «$props.id()»Эта руна, появившаяся в версии 5.20.0, создаёт уникальный идентификатор для конкретного экземпляра компонента. При гидратации серверного рендеринга значение сохраняется как на сервере, так и на клиенте.
Это особенно удобно для связывания элементов с помощью атрибутов, таких как for и aria-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>