bind:
Данные обычно передаются сверху вниз, от родителя к дочернему компоненту. Директива bind:
позволяет передавать данные в обратном направлении, от дочернего компонента к родительскому.
Общая синтаксическая структура — bind:property={expression}
, где expression
является lvalue (т. е. переменной или свойством объекта). Когда выражение является идентификатором с тем же именем, что и свойство, мы можем опустить выражение — другими словами, эти два варианта эквивалентны:
<input bind:value={value} />
<input bind:value />
Svelte создаёт обработчик событий, который обновляет связанное значение. Если элемент уже имеет обработчик для того же события, этот обработчик будет вызван перед обновлением связанного значения.
Большинство привязок являются двусторонними, что означает, что изменения значения будут влиять на элемент и наоборот. Некоторые привязки являются только для чтения, что означает, что изменение их значения не повлияет на элемент.
Привязки функций
Вы также можете использовать bind:property={get, set}
, где get
и set
— это функции, позволяющие выполнять валидацию и преобразование:
<input bind:value={
() => value,
(v) => value = v.toLowerCase()}
/>
В случае привязок только для чтения, таких как привязки размеров, значение get
должно быть null
:
<div
bind:clientWidth={null, redraw}
bind:clientHeight={null, redraw}
>...</div>
<input bind:value>
Директива bind:value
на элементе <input>
устанавливает связь со свойством value
этого элемента ввода:
<script>
let message = $state('привет');
</script>
<input bind:value={message} />
<p>{message}</p>
В случае числового ввода (type="number"
или type="range"
) значение будет преобразовано в число (демонстрация):
<script>
let a = $state(1);
let b = $state(2);
</script>
<label>
<input type="number" bind:value={a} min="0" max="10" />
<input type="range" bind:value={a} min="0" max="10" />
</label>
<label>
<input type="number" bind:value={b} min="0" max="10" />
<input type="range" bind:value={b} min="0" max="10" />
</label>
<p>{a} + {b} = {a + b}</p>
Если ввод пустой или недействителен (в случае type="number"
), значение будет undefined
.
Начиная с версии 5.6.0, если у <input>
есть defaultValue
и он является частью формы, он будет возвращаться к этому значению вместо пустой строки при сбросе формы. Обратите внимание, что для первоначального рендера значение привязки имеет приоритет, если оно не равно null
или undefined
.
<script>
let value = $state('');
</script>
<form>
<input bind:value defaultValue="не пустая строка">
<input type="reset" value="Сброс">
</form>
<input bind:checked>
Флажки и переключатели могут быть связаны с помощью bind:checked
:
<label>
<input type="checkbox" bind:checked={accepted} />
Принять правила и условия
</label>
Начиная с версии 5.6.0, если у <input>
есть атрибут defaultChecked
и он является частью формы, он будет возвращаться к этому значению вместо false
при сбросе формы. Обратите внимание, что для первоначального рендера значение привязки имеет приоритет, если оно не равно null
или undefined
.
<script>
let checked = $state(true);
</script>
<form>
<input type="checkbox" bind:checked defaultChecked={true}>
<input type="reset" value="Сброс">
</form>
<input bind:group>
Элементы ввода, которые работают вместе, могут использовать bind:group
:
<script>
let tortilla = $state('Обычная');
/** @type {Array<string>} */
let fillings = $state([]);
</script>
<!-- сгруппированные переключатели являются взаимоисключающими -->
<input type="radio" bind:group={tortilla} value="Обычная" />
<input type="radio" bind:group={tortilla} value="Цельнозерновая" />
<input type="radio" bind:group={tortilla} value="Шпинат" />
<!-- сгруппированные флажки формируют массив -->
<input type="checkbox" bind:group={fillings} value="Рис" />
<input type="checkbox" bind:group={fillings} value="Фасоль" />
<input type="checkbox" bind:group={fillings} value="Сыр" />
<input type="checkbox" bind:group={fillings} value="Гуакамоле (дополнительно)" />
<input bind:files>
На элементах <input>
с type="file"
вы можете использовать bind:files
, чтобы получить FileList
выбранных файлов. Когда вы хотите обновить файлы программно, вам всегда нужно использовать объект FileList
. В настоящее время объекты FileList
не могут быть созданы напрямую, поэтому вам нужно создать новый объект DataTransfer
и получить files
оттуда.
<script>
let files = $state();
function clear() {
files = new DataTransfer().files; // null или undefined не работают
}
</script>
<label for="avatar">Загрузите картинку:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
<button onclick={clear}>очистить</button>
Объекты FileList
также не могут быть изменены, поэтому, если вы хотите, например, удалить один файл из списка, вам нужно создать новый объект DataTransfer
и добавить в него файлы, которые вы хотите сохранить.
<select bind:value>
Привязка значения <select>
соответствует свойству value
выбранного <option>
, которое может быть любым значением (не только строками, как это обычно происходит в DOM):
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b}>b</option>
<option value={c}>c</option>
</select>
Элемент <select multiple>
ведет себя аналогично группе флажков. Связанная переменная представляет собой массив, в котором каждая запись соответствует свойству value
каждого выбранного <option>
:
<select multiple bind:value={fillings}>
<option value="Рис">Рис</option>
<option value="Фасоль">Фасоль</option>
<option value="Сыр">Сыр</option>
<option value="Гуакамоле (дополнительно)">Гуакамоле (дополнительно)</option>
</select>
Когда значение <option>
совпадает с его текстовым содержимым, атрибут можно опустить:
<select multiple bind:value={fillings}>
<option>Рис</option>
<option>Фасоль</option>
<option>Сыр</option>
<option>Гуакамоле (дополнительно)</option>
</select>
Вы можете задать <select>
значение по умолчанию, добавив атрибут selected
к <option>
(или к нескольким опциям в случае <select multiple>
), которые должны быть выбраны изначально. Если <select>
является частью формы, он вернется к этому выбору, когда форма будет сброшена. Обратите внимание, что для первоначального рендеринга значение привязки имеет приоритет, если оно не равно undefined
:
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b} selected>b</option>
<option value={c}>c</option>
</select>
<audio>
Элементы <audio>
имеют свой собственный набор привязок — пять двусторонних…
…и шесть только для чтения:
<audio src={clip} bind:duration bind:currentTime bind:paused></audio>
<video>
Элементы <video>
имеют все те же привязки, что и элементы <audio>
, плюс привязки только для чтения videoWidth
и videoHeight
.
<img>
Элементы <img>
имеют две привязки только для чтения:
<details bind:open>
Элементы <details>
поддерживают привязку к свойству open
:
<details bind:open={isOpen}>
<summary>Что ты делаешь с ошибкой JavaScript?</summary>
<p>Ты выводишь её в консоль.</p>
</details>
Привязки к элементам с атрибутом contenteditable
Элементы с атрибутом contenteditable
поддерживают следующие привязки:
<div contenteditable="true" bind:innerHTML={html}></div>
Размеры
Все видимые элементы имеют следующие привязки только для чтения, измеряемые с помощью ResizeObserver
:
<div bind:offsetWidth={width} bind:offsetHeight={height}>
<Chart {width} {height} />
</div>
bind:this
bind:this={dom_node}
Чтобы получить ссылку на узел DOM, используйте bind:this
. Значение будет undefined
до тех пор, пока компонент не будет смонтирован — другими словами, вы должны считывать его внутри эффекта или обработчика событий, но не во время инициализации компонента:
<script>
/** @type {HTMLCanvasElement} */
let canvas;
$effect(() => {
const ctx = canvas.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvas}></canvas>
Компоненты также поддерживают bind:this
, что позволяет вам программно взаимодействовать с экземплярами компонентов.
// App.svelte
<ShoppingCart bind:this={cart} />
<button onclick={() => cart.empty()}> Очистить корзину покупок </button>
// ShoppingCart.svelte
<script>
// Все экспорты экземпляра доступны в объекте экземпляра
export function empty() {
// ...
}
</script>
// ShoppingCart.svelte
<script lang="ts">
// Все экспорты экземпляра доступны в объекте экземпляра
export function empty() {
// ...
}
</script>
bind:property для компонентов
bind:property={variable}
Вы можете привязываться к свойствам компонента, используя тот же синтаксис, что и для элементов:
<Keypad bind:value={pin} />
Хотя свойства в Svelte реагируют на изменения без необходимости привязки, по умолчанию эта реактивность направлена только вниз к компоненту. Применение bind:property
позволяет изменениям, происходящим внутри компонента, возвращаться обратно наружу.
Чтобы пометить свойство как привязываемое, используйте руну $bindable
:
<script>
let { readonlyProperty, bindableProperty = $bindable() } = $props();
</script>
Объявление свойства как привязываемого означает, что его можно использовать с помощью bind:
, но это не означает, что его обязательно нужно использовать с bind:
.
Привязываемые свойства могут иметь значение по умолчанию:
<script>
let { bindableProperty = $bindable('значение по умолчанию') } = $props();
</script>
Это значение по умолчанию применяется только в том случае, если свойство не привязано. Когда свойство привязано и присутствует значение по умолчанию, родительский компонент должен предоставить значение, отличное от undefined
, в противном случае будет выброшена ошибка во время выполнения. Это предотвращает ситуации, которые трудно анализировать, когда неясно, какое значение должно применяться.