0
0
mirror of https://github.com/sveltejs/svelte.git synced 2024-12-01 17:30:59 +01:00
svelte/site/content/guide/08-bindings.md
2018-12-24 16:20:57 -05:00

4.9 KiB

title
Bindings

Bindings

As we've seen, data can be passed down to elements and components with attributes and props. Occasionally, you need to get data back up; for that we use bindings.

Component bindings

Component bindings keep values in sync between a parent and a child:

<!-- { repl: false } -->
<Widget bind:childValue=parentValue/>

Whenever childValue changes in the child component, parentValue will be updated in the parent component and vice versa.

If the names are the same, you can shorten the declaration:

<!-- { repl: false } -->
<Widget bind:value/>

Use component bindings judiciously. They can save you a lot of boilerplate, but will make it harder to reason about data flow within your application if you overuse them.

Element bindings

Element bindings make it easy to respond to user interactions:

<!-- { title: 'Element bindings' } -->
<h1>Hello {name}!</h1>
<input bind:value=name>
/* { hidden: true } */
{
	name: 'world'
}

Some bindings are one-way, meaning that the values are read-only. Most are two-way — changing the data programmatically will update the DOM. The following bindings are available:

Name Applies to Kind
value <input> <textarea> <select> Two-way
checked indeterminate <input type=checkbox> Two-way
group (see note) <input type=checkbox> <input type=radio> Two-way
currentTime paused played volume <audio> <video> Two-way
buffered duration seekable <audio> <video> One-way
offsetWidth offsetHeight clientWidth clientHeight All block-level elements One-way
scrollX scrollY <svelte:window> Two-way
online innerWidth innerHeight outerWidth outerHeight <svelte:window> One-way

'group' bindings allow you to capture the current value of a set of radio inputs, or all the selected values of a set of checkbox inputs.

Here is a complete example of using two way bindings with a form:

<!-- { title: 'Form bindings' } -->
<form on:submit="handleSubmit(event)">
	<input bind:value=name type=text>
	<button type=submit>Say hello</button>
</form>

<script>
	export default {
		methods: {
			handleSubmit(event) {
				// prevent the page from reloading
				event.preventDefault();

				const { name } = this.get();
				alert(`Hello ${name}!`);
			}
		}
	};
</script>
/* { hidden: true } */
{
	name: "world"
}

'two way' bindings allow you to update a value in a nested property as seen in this checkbox input example.

bind:this

There's a special binding that exists on all elements and components — this. It allows you to store a reference to a DOM node or component instance so that you can interact with it programmatically:

<!-- { title: 'Refs' } -->
<canvas bind:this={canvas} width={200} height={200}></canvas>

<script>
	import { onMount } from 'svelte';
	import createRenderer from './createRenderer.js';

	let canvas;

	onMount(() => {
		const ctx = canvas.getContext('2d');
		const renderer = createRenderer(canvas, ctx);

		// stop updating the canvas when
		// the component is destroyed
		return renderer.stop;
	});
</script>
/* { filename: 'createRenderer.js', hidden: true } */
export default function createRenderer(canvas, ctx) {
	let running = true;
	loop();

	return {
		stop: () => {
			running = false;
		}
	};

	function loop() {
		if (!running) return;
		requestAnimationFrame(loop);

		const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

		for (let p = 0; p < imageData.data.length; p += 4) {
			const i = p / 4;
			const x = i % canvas.width;
			const y = i / canvas.height >>> 0;

			const t = window.performance.now();

			const r = 64 + (128 * x / canvas.width) + (64 * Math.sin(t / 1000));
			const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1000));
			const b = 128;

			imageData.data[p + 0] = r;
			imageData.data[p + 1] = g;
			imageData.data[p + 2] = b;
			imageData.data[p + 3] = 255;
		}

		ctx.putImageData(imageData, 0, 0);
	}
}