mirror of https://github.com/sveltejs/svelte
parent
4f6ffc4612
commit
991e46422b
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Nested answer={42}/>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
let answer;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>The answer is {answer}</p>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Nested answer={42}/>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
export let answer;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>The answer is {answer}</p>
|
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: Declaring props
|
||||||
|
---
|
||||||
|
|
||||||
|
So far, we've dealt exclusively with internal state — that is to say, the values are only accessible within a given component.
|
||||||
|
|
||||||
|
In any real application, you'll need to pass data from one component down to its children. To do that, we need to declare *properties*, generally shortened to 'props'. In Svelte, we do that with the `export` keyword. Edit the `Nested.svelte` component:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
export let answer;
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
> Just like `$:`, this may feel a little weird at first. That's not how `export` normally works in JavaScript modules! Just roll with it for now — it'll soon become second nature.
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Nested answer={42}/>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
export let answer;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>The answer is {answer}</p>
|
@ -0,0 +1,6 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Nested answer={42}/>
|
||||||
|
<Nested/>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
export let answer = 'a mystery';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>The answer is {answer}</p>
|
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
title: Default values
|
||||||
|
---
|
||||||
|
|
||||||
|
We can easily specify default values for props:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
export let answer = 'a mystery';
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
If we now instantiate the component without an `answer` prop, it will fall back to the default:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<Nested answer={42}/>
|
||||||
|
<Nested/>
|
||||||
|
```
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"title": "Props"
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
let m = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
function handleMousemove(event) {
|
||||||
|
m.x = event.clientX;
|
||||||
|
m.y = event.clientY;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div { width: 100%; height: 100%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
The mouse position is {m.x} x {m.y}
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
let m = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
function handleMousemove(event) {
|
||||||
|
m.x = event.clientX;
|
||||||
|
m.y = event.clientY;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div { width: 100%; height: 100%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div on:mousemove={handleMousemove}>
|
||||||
|
The mouse position is {m.x} x {m.y}
|
||||||
|
</div>
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: DOM events
|
||||||
|
---
|
||||||
|
|
||||||
|
As we briefly saw in an [earlier chapter](tutorial/reactive-assignments), you can listen to any event on an element with the `on:` directive:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div on:mousemove={handleMousemove}>
|
||||||
|
The mouse position is {m.x} x {m.y}
|
||||||
|
</div>
|
||||||
|
```
|
@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
let m = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
function handleMousemove(event) {
|
||||||
|
m.x = event.clientX;
|
||||||
|
m.y = event.clientY;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div { width: 100%; height: 100%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div on:mousemove={handleMousemove}>
|
||||||
|
The mouse position is {m.x} x {m.y}
|
||||||
|
</div>
|
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
let m = { x: 0, y: 0 };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div { width: 100%; height: 100%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
|
||||||
|
The mouse position is {m.x} x {m.y}
|
||||||
|
</div>
|
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: Inline handlers
|
||||||
|
---
|
||||||
|
|
||||||
|
You can also declare event handlers inline:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
|
||||||
|
The mouse position is {m.x} x {m.y}
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
The quote marks are optional, but they're helpful for syntax highlighting in some environments.
|
||||||
|
|
||||||
|
> In some frameworks you may see recommendations to avoid inline event handlers for performance reasons, particularly inside loops. That advice doesn't apply to Svelte — the compiler will always do the right thing, whichever form you choose.
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
function handleClick() {
|
||||||
|
alert('clicked')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={handleClick}>
|
||||||
|
Click me
|
||||||
|
</button>
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
function handleClick() {
|
||||||
|
alert('no more alerts')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click|once={handleClick}>
|
||||||
|
Click me
|
||||||
|
</button>
|
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: Event modifiers
|
||||||
|
---
|
||||||
|
|
||||||
|
DOM event handlers can have *modifiers* that alter their behaviour. For example, a handler with a `once` modifier will only run a single time:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
function handleClick() {
|
||||||
|
alert('no more alerts')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click|once={handleClick}>
|
||||||
|
Click me
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
The full list of modifiers:
|
||||||
|
|
||||||
|
* `preventDefault` — calls `event.preventDefault()` before running the handler. Useful for e.g. client-side form handling
|
||||||
|
* `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
|
||||||
|
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
|
||||||
|
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase
|
||||||
|
* `once`
|
||||||
|
|
||||||
|
You can chain modifiers together, e.g. `on:click|once|capture={...}`.
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import Inner from './Inner.svelte';
|
||||||
|
|
||||||
|
function handleMessage(event) {
|
||||||
|
alert(event.detail.text);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Inner on:message={handleMessage}/>
|
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
// setup code goes here
|
||||||
|
|
||||||
|
function sayHello() {
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={sayHello}>
|
||||||
|
Click to say hello
|
||||||
|
</button>
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import Inner from './Inner.svelte';
|
||||||
|
|
||||||
|
function handleMessage(event) {
|
||||||
|
alert(event.detail.text);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Inner on:message={handleMessage}/>
|
@ -0,0 +1,15 @@
|
|||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function sayHello() {
|
||||||
|
dispatch('message', {
|
||||||
|
text: 'Hello!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={sayHello}>
|
||||||
|
Click to say hello
|
||||||
|
</button>
|
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: Component events
|
||||||
|
---
|
||||||
|
|
||||||
|
Components can also dispatch events. To do so, they must create an event dispatcher. Update `Inner.svelte`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function sayHello() {
|
||||||
|
dispatch('message', {
|
||||||
|
text: 'Hello!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
> `createEventDispatcher` must be called when the component is first instantiated — you can't do it later inside e.g. a `setTimeout` callback. This links `dispatch` to the component instance.
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import Outer from './Outer.svelte';
|
||||||
|
|
||||||
|
function handleMessage(event) {
|
||||||
|
alert(event.detail.text);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Outer on:message={handleMessage}/>
|
@ -0,0 +1,15 @@
|
|||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function sayHello() {
|
||||||
|
dispatch('message', {
|
||||||
|
text: 'Hello!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={sayHello}>
|
||||||
|
Click to say hello
|
||||||
|
</button>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import Inner from './Inner.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Inner/>
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import Outer from './Outer.svelte';
|
||||||
|
|
||||||
|
function handleMessage(event) {
|
||||||
|
alert(event.detail.text);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Outer on:message={handleMessage}/>
|
@ -0,0 +1,15 @@
|
|||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function sayHello() {
|
||||||
|
dispatch('message', {
|
||||||
|
text: 'Hello!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={sayHello}>
|
||||||
|
Click to say hello
|
||||||
|
</button>
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import Inner from './Inner.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Inner on:message/>
|
@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: Event forwarding
|
||||||
|
---
|
||||||
|
|
||||||
|
Unlike DOM events, component events don't *bubble*. If you want to listen to an event on some deeply nested component, the intermediate components must *forward* the event.
|
||||||
|
|
||||||
|
In this case, we have the same `App.svelte` and `Inner.svelte` as in the [previous chapter](tutorial/component-events), but there's now an `Outer.svelte` component that contains `<Inner/>`.
|
||||||
|
|
||||||
|
One way we could solve the problem is adding `createEventDispatcher` to `Outer.svelte`, listening for the `message` event, and creating a handler for it:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
import Inner from './Inner.svelte';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function forward(event) {
|
||||||
|
dispatch('message', event.detail);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Inner on:message={forward}/>
|
||||||
|
```
|
||||||
|
|
||||||
|
But that's a lot of code to write, so Svelte gives us an equivalent shorthand — an `on:message` event directive without a value means 'forward all `message` events'.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
import Inner from './Inner.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Inner on:message/>
|
||||||
|
```
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import FancyButton from './FancyButton.svelte';
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
alert('clicked');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FancyButton on:click={handleClick}/>
|
@ -0,0 +1,15 @@
|
|||||||
|
<style>
|
||||||
|
button {
|
||||||
|
font-family: 'Comic Sans MS';
|
||||||
|
font-size: 2em;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
color: royalblue;
|
||||||
|
background: gold;
|
||||||
|
border-radius: 1em;
|
||||||
|
box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<button>
|
||||||
|
Click me
|
||||||
|
</button>
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import FancyButton from './FancyButton.svelte';
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
alert('clicked');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FancyButton on:click={handleClick}/>
|
@ -0,0 +1,15 @@
|
|||||||
|
<style>
|
||||||
|
button {
|
||||||
|
font-family: 'Comic Sans MS';
|
||||||
|
font-size: 2em;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
color: royalblue;
|
||||||
|
background: gold;
|
||||||
|
border-radius: 1em;
|
||||||
|
box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<button on:click>
|
||||||
|
Click me
|
||||||
|
</button>
|
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: DOM event forwarding
|
||||||
|
---
|
||||||
|
|
||||||
|
Event forwarding works for DOM events too.
|
||||||
|
|
||||||
|
We want to get notified of clicks on our `<FancyButton>` — to do that, we just need to forward `click` events on the `<button>` element in `FancyButton.svelte`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button on:click>
|
||||||
|
Click me
|
||||||
|
</button>
|
||||||
|
```
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"title": "Events"
|
||||||
|
}
|
Loading…
Reference in new issue