From d68fd1694f5e495e25ec3a1efe4e48f1b681ccc6 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 21 Oct 2024 21:04:10 +0200 Subject: [PATCH 1/8] docs: legacy docs add docs on old syntax --- .../docs/01-introduction/03-svelte-files.md | 3 + .../01-introduction/04-svelte-js-files.md | 3 + .../docs/02-runes/01-what-are-runes.md | 3 + .../docs/99-legacy/00-legacy-overview.md | 7 + documentation/docs/99-legacy/01-legacy-let.md | 49 +++++ .../02-legacy-reactive-statements.md | 87 ++++++++ .../docs/99-legacy/03-legacy-export-let.md | 63 ++++++ .../docs/99-legacy/04-legacy-$$props.md | 12 ++ .../docs/99-legacy/05-legacy-$$restProps.md | 12 ++ documentation/docs/99-legacy/10-legacy-on.md | 129 ++++++++++++ .../docs/99-legacy/20-legacy-slots.md | 124 +++++++++++ .../docs/99-legacy/21-legacy-$$slots.md | 28 +++ .../99-legacy/22-legacy-svelte-fragment.md | 26 +++ .../99-legacy/30-legacy-svelte-component.md | 27 +++ .../docs/99-legacy/31-legacy-svelte-self.md | 37 ++++ .../docs/99-legacy/40-legacy-component-api.md | 198 ++++++++++++++++++ documentation/docs/99-legacy/index.md | 3 + 17 files changed, 811 insertions(+) create mode 100644 documentation/docs/99-legacy/00-legacy-overview.md create mode 100644 documentation/docs/99-legacy/01-legacy-let.md create mode 100644 documentation/docs/99-legacy/02-legacy-reactive-statements.md create mode 100644 documentation/docs/99-legacy/03-legacy-export-let.md create mode 100644 documentation/docs/99-legacy/04-legacy-$$props.md create mode 100644 documentation/docs/99-legacy/05-legacy-$$restProps.md create mode 100644 documentation/docs/99-legacy/10-legacy-on.md create mode 100644 documentation/docs/99-legacy/20-legacy-slots.md create mode 100644 documentation/docs/99-legacy/21-legacy-$$slots.md create mode 100644 documentation/docs/99-legacy/22-legacy-svelte-fragment.md create mode 100644 documentation/docs/99-legacy/30-legacy-svelte-component.md create mode 100644 documentation/docs/99-legacy/31-legacy-svelte-self.md create mode 100644 documentation/docs/99-legacy/40-legacy-component-api.md create mode 100644 documentation/docs/99-legacy/index.md diff --git a/documentation/docs/01-introduction/03-svelte-files.md b/documentation/docs/01-introduction/03-svelte-files.md index f534e30fcb21..e3dd72c222e9 100644 --- a/documentation/docs/01-introduction/03-svelte-files.md +++ b/documentation/docs/01-introduction/03-svelte-files.md @@ -50,6 +50,9 @@ A ` +``` + +Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. A subsequent assignment is required to trigger the update. This and more details can also be found in the [tutorial](https://learn.svelte.dev/tutorial/updating-arrays-and-objects). + +```svelte + +``` + +Svelte's ` +``` + +> [!NOTE] +> In Svelte 5+, state is explicitly reactive via the [`$state` rune]($state) diff --git a/documentation/docs/99-legacy/02-legacy-reactive-statements.md b/documentation/docs/99-legacy/02-legacy-reactive-statements.md new file mode 100644 index 000000000000..bbf14a7241a0 --- /dev/null +++ b/documentation/docs/99-legacy/02-legacy-reactive-statements.md @@ -0,0 +1,87 @@ +--- +title: $: +--- + +Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run after other script code and before the component markup is rendered, whenever the values that they depend on have changed. + +```svelte + +``` + +Only values which directly appear within the `$:` block will become dependencies of the reactive statement. For example, in the code below `total` will only update when `x` changes, but not `y`. + +```svelte + + + +Total: {total} + + + +``` + +It is important to note that the reactive blocks are ordered via simple static analysis at compile time, and all the compiler looks at are the variables that are assigned to and used within the block itself, not in any functions called by them. This means that `yDependent` will not be updated when `x` is updated in the following example: + +```svelte + + +``` + +Moving the line `$: yDependent = y` below `$: setY(x)` will cause `yDependent` to be updated when `x` is updated. + +If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf. + +```svelte + + +``` + +> [!NOTE] +> In Svelte 5+, reactions are handled via the [`$derived`]($derived) and [`$effect`]($effect) runes diff --git a/documentation/docs/99-legacy/03-legacy-export-let.md b/documentation/docs/99-legacy/03-legacy-export-let.md new file mode 100644 index 000000000000..75ff14d4e135 --- /dev/null +++ b/documentation/docs/99-legacy/03-legacy-export-let.md @@ -0,0 +1,63 @@ +--- +title: export let +--- + +Svelte uses the `export` keyword to mark a variable declaration as a _property_ or _prop_, which means it becomes accessible to consumers of the component (see the section on [attributes and props](/docs/basic-markup#attributes-and-props) for more information). + +```svelte + +``` + +You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is `undefined`) when instantiating the component. Note that if the values of props are subsequently updated, then any prop whose value is not specified will be set to `undefined` (rather than its initial value). + +In development mode (see the [compiler options](/docs/svelte-compiler#compile)), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is `undefined`. + +```svelte + +``` + +If you export a `const`, `class` or `function`, it is readonly from outside the component. Functions are valid prop values, however, as shown below. + +```svelte + + +``` + +Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs/component-directives#bind-this). + +You can use reserved words as prop names. + +```svelte + + +``` + +> [!NOTE] +> In Svelte 5+, use the [`$props`]($props) rune instead diff --git a/documentation/docs/99-legacy/04-legacy-$$props.md b/documentation/docs/99-legacy/04-legacy-$$props.md new file mode 100644 index 000000000000..32f64287f0f4 --- /dev/null +++ b/documentation/docs/99-legacy/04-legacy-$$props.md @@ -0,0 +1,12 @@ +--- +title: $$props +--- + +`$$props` references all props that are passed to a component, including ones that are not declared with `export`. Using `$$props` will not perform as well as references to a specific prop because changes to any prop will cause Svelte to recheck all usages of `$$props`. But it can be useful in some cases – for example, when you don't know at compile time what props might be passed to a component. + +```svelte + +``` + +> [!NOTE] +> In Svelte 5+, this concept is unnecessary as you can use [`let prop = $props()`]($props) instead diff --git a/documentation/docs/99-legacy/05-legacy-$$restProps.md b/documentation/docs/99-legacy/05-legacy-$$restProps.md new file mode 100644 index 000000000000..db84a9103056 --- /dev/null +++ b/documentation/docs/99-legacy/05-legacy-$$restProps.md @@ -0,0 +1,12 @@ +--- +title: $$restProps +--- + +`$$restProps` contains only the props which are _not_ declared with `export`. It can be used to pass down other unknown attributes to an element in a component. It shares the same performance characteristics compared to specific property access as `$$props`. + +```svelte + +``` + +> [!NOTE] +> In Svelte 5+, this concept is unnecessary as you can use [`let { foo, ...rest } = $props()`]($props) instead diff --git a/documentation/docs/99-legacy/10-legacy-on.md b/documentation/docs/99-legacy/10-legacy-on.md new file mode 100644 index 000000000000..9584a9aa707e --- /dev/null +++ b/documentation/docs/99-legacy/10-legacy-on.md @@ -0,0 +1,129 @@ +--- +title: on: +--- + +```svelte + +on:eventname={handler} +``` + +```svelte + +on:eventname|modifiers={handler} +``` + +Use the `on:` directive to listen to DOM events. + +```svelte + + + + +``` + +Handlers can be declared inline with no performance penalty. As with attributes, directive values may be quoted for the sake of syntax highlighters. + +```svelte + +``` + +Add _modifiers_ to DOM events with the `|` character. + +```svelte +
+ +
+``` + +The following modifiers are available: + +- `preventDefault` — calls `event.preventDefault()` before running the handler +- `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element +- `stopImmediatePropagation` - calls `event.stopImmediatePropagation()`, preventing other listeners of the same event from being fired. +- `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so) +- `nonpassive` — explicitly set `passive: false` +- `capture` — fires the handler during the _capture_ phase instead of the _bubbling_ phase +- `once` — remove the handler after the first time it runs +- `self` — only trigger handler if `event.target` is the element itself +- `trusted` — only trigger handler if `event.isTrusted` is `true`. I.e. if the event is triggered by a user action. + +Modifiers can be chained together, e.g. `on:click|once|capture={...}`. + +If the `on:` directive is used without a value, the component will _forward_ the event, meaning that a consumer of the component can listen for it. + +```svelte + +``` + +It's possible to have multiple event listeners for the same event: + +```svelte + + + + +``` + +> [!NOTE] +> In Svelte 5+, use event attributes instead +> ```svelte +> +> ``` + +## Component events + +Component events created with [`createEventDispatcher`](svelte#createEventDispatcher) create a `CustomEvent`. These events do not bubble. The detail argument corresponds to the `CustomEvent.detail` property and can contain any type of data. + +```svelte + + + +``` + +Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object. + +```svelte + + + +``` + +> [!NOTE] +> If you're planning on migrating to Svelte 5, use callback props instead. This will make upgrading easier as `createEventDispatcher` is deprecated +> ```svelte +> +> +> +> ``` diff --git a/documentation/docs/99-legacy/20-legacy-slots.md b/documentation/docs/99-legacy/20-legacy-slots.md new file mode 100644 index 000000000000..a82d8435bff0 --- /dev/null +++ b/documentation/docs/99-legacy/20-legacy-slots.md @@ -0,0 +1,124 @@ +--- +title: +--- + +```svelte + +``` + +```svelte + +``` + +```svelte + +``` + +Components can have child content, in the same way that elements can. + +The content is exposed in the child component using the `` element, which can contain fallback content that is rendered if no children are provided. + +```svelte + +
+ + this fallback content will be rendered when no content is provided, like in the first example + +
+ + + + + + +

this is some child content that will overwrite the default slot content

+
+``` + +Note: If you want to render regular `` element, You can use ``. + +> [!NOTE] +> In Svelte 5+, use snippets instead + +## `` + +Named slots allow consumers to target specific areas. They can also have fallback content. + +```svelte + +
+ No header was provided +

Some content between header and footer

+ +
+ + + +

Hello

+

Copyright (c) 2019 Svelte Industries

+
+``` + +Components can be placed in a named slot using the syntax ``. +In order to place content in a slot without using a wrapper element, you can use the special element ``. + +```svelte + +
+ No header was provided +

Some content between header and footer

+ +
+ + + + + +

All rights reserved.

+

Copyright (c) 2019 Svelte Industries

+
+
+``` + +## `` + +Slots can be rendered zero or more times and can pass values _back_ to the parent using props. The parent exposes the values to the slot template using the `let:` directive. + +The usual shorthand rules apply — `let:item` is equivalent to `let:item={item}`, and `` is equivalent to ``. + +```svelte + +
    + {#each items as item} +
  • + +
  • + {/each} +
+ + + +
{thing.text}
+
+``` + +Named slots can also expose values. The `let:` directive goes on the element with the `slot` attribute. + +```svelte + +
    + {#each items as item} +
  • + +
  • + {/each} +
+ + + + + +
{item.text}
+

Copyright (c) 2019 Svelte Industries

+
+``` diff --git a/documentation/docs/99-legacy/21-legacy-$$slots.md b/documentation/docs/99-legacy/21-legacy-$$slots.md new file mode 100644 index 000000000000..ad5fce6c801c --- /dev/null +++ b/documentation/docs/99-legacy/21-legacy-$$slots.md @@ -0,0 +1,28 @@ +--- +title: $$slots +--- + +`$$slots` is an object whose keys are the names of the slots passed into the component by the parent. If the parent does not pass in a slot with a particular name, that name will not be present in `$$slots`. This allows components to render a slot (and other elements, like wrappers for styling) only if the parent provides it. + +Note that explicitly passing in an empty named slot will add that slot's name to `$$slots`. For example, if a parent passes `
` to a child component, `$$slots.title` will be truthy within the child. + +```svelte + +
+ + {#if $$slots.description} + +
+ + {/if} +
+ + + +

Blog Post Title

+ +
+``` + +> [!NOTE] +> In Svelte 5+, this concept is obsolete, as you pass snippets as component props and can check whether or not that prop is set diff --git a/documentation/docs/99-legacy/22-legacy-svelte-fragment.md b/documentation/docs/99-legacy/22-legacy-svelte-fragment.md new file mode 100644 index 000000000000..99fe192f5a56 --- /dev/null +++ b/documentation/docs/99-legacy/22-legacy-svelte-fragment.md @@ -0,0 +1,26 @@ +--- +title: +--- + +The `` element allows you to place content in a [named slot](/docs/special-elements#slot-slot-name-name) without wrapping it in a container DOM element. This keeps the flow layout of your document intact. + +```svelte + +
+ No header was provided +

Some content between header and footer

+ +
+ + + +

Hello

+ +

All rights reserved.

+

Copyright (c) 2019 Svelte Industries

+
+
+``` + +> [!NOTE] +> In Svelte 5+, this concept is obsolete, as snippets don't create a wrapping element diff --git a/documentation/docs/99-legacy/30-legacy-svelte-component.md b/documentation/docs/99-legacy/30-legacy-svelte-component.md new file mode 100644 index 000000000000..2c04238f2d56 --- /dev/null +++ b/documentation/docs/99-legacy/30-legacy-svelte-component.md @@ -0,0 +1,27 @@ +--- +title: +--- + +```svelte + +``` + +The `` element renders a component dynamically, using the component constructor specified as the `this` property. When the property changes, the component is destroyed and recreated. + +If `this` is falsy, no component is rendered. + +```svelte + +``` + +> [!NOTE] +> In Svelte 5+, this concept is obsolete, as you can just reference `$state` or `$derived` variables containing components +> ```svelte +> +> +> +> +> +> ``` diff --git a/documentation/docs/99-legacy/31-legacy-svelte-self.md b/documentation/docs/99-legacy/31-legacy-svelte-self.md new file mode 100644 index 000000000000..b601eae62aa3 --- /dev/null +++ b/documentation/docs/99-legacy/31-legacy-svelte-self.md @@ -0,0 +1,37 @@ +--- +title: +--- + +The `` element allows a component to include itself, recursively. + +It cannot appear at the top level of your markup; it must be inside an if or each block or passed to a component's slot to prevent an infinite loop. + +```svelte + + +{#if count > 0} +

counting down... {count}

+ +{:else} +

lift-off!

+{/if} +``` + +> [!NOTE] +> This concept is obsolete, as you can just self-import components +> ```svelte +> +> +> +> {#if count > 0} +>

counting down... {count}

+> +> {:else} +>

lift-off!

+> {/if} +> ``` diff --git a/documentation/docs/99-legacy/40-legacy-component-api.md b/documentation/docs/99-legacy/40-legacy-component-api.md new file mode 100644 index 000000000000..26b3a310714d --- /dev/null +++ b/documentation/docs/99-legacy/40-legacy-component-api.md @@ -0,0 +1,198 @@ +--- +title: Imperative component API +--- + +## Creating a component + +```ts +// @noErrors +const component = new Component(options); +``` + +A client-side component — that is, a component compiled with `generate: 'dom'` (or the `generate` option left unspecified) is a JavaScript class. + +```ts +// @noErrors +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + // assuming App.svelte contains something like + // `export let answer`: + answer: 42 + } +}); +``` + +The following initialisation options can be provided: + +| option | default | description | +| --------- | ----------- | ---------------------------------------------------------------------------------------------------- | +| `target` | **none** | An `HTMLElement` or `ShadowRoot` to render to. This option is required | +| `anchor` | `null` | A child of `target` to render the component immediately before | +| `props` | `{}` | An object of properties to supply to the component | +| `context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component | +| `hydrate` | `false` | See below | +| `intro` | `false` | If `true`, will play transitions on initial render, rather than waiting for subsequent state changes | + +Existing children of `target` are left where they are. + +The `hydrate` option instructs Svelte to upgrade existing DOM (usually from server-side rendering) rather than creating new elements. It will only work if the component was compiled with the [`hydratable: true` option](/docs/svelte-compiler#compile). Hydration of `` elements only works properly if the server-side rendering code was also compiled with `hydratable: true`, which adds a marker to each element in the `` so that the component knows which elements it's responsible for removing during hydration. + +Whereas children of `target` are normally left alone, `hydrate: true` will cause any children to be removed. For that reason, the `anchor` option cannot be used alongside `hydrate: true`. + +The existing DOM doesn't need to match the component — Svelte will 'repair' the DOM as it goes. + +```ts +/// file: index.js +// @noErrors +import App from './App.svelte'; + +const app = new App({ + target: document.querySelector('#server-rendered-html'), + hydrate: true +}); +``` + +> [!NOTE] +> In Svelte 5+, use [`mount`](svelte#mount) instead + +## `$set` + +```ts +// @noErrors +component.$set(props); +``` + +Programmatically sets props on an instance. `component.$set({ x: 1 })` is equivalent to `x = 1` inside the component's ` + + ``` -Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. A subsequent assignment is required to trigger the update. This and more details can also be found in the [tutorial](https://learn.svelte.dev/tutorial/updating-arrays-and-objects). +Because Svelte's legacy mode reactivity is based on _assignments_, using array methods like `.push()` and `.splice()` won't automatically trigger updates. A subsequent assignment is required to 'tell' the compiler to update the UI: ```svelte -``` + numbers.push(numbers.length + 1); -Svelte's ` ``` - -> [!NOTE] -> In Svelte 5+, state is explicitly reactive via the [`$state` rune]($state) From 54d76c97f1e760167ea31de016a3432190cbdba6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 21 Oct 2024 21:44:07 -0400 Subject: [PATCH 4/8] tweak --- documentation/docs/99-legacy/01-legacy-let.md | 2 +- .../02-legacy-reactive-assignments.md | 87 +++++++++++++++++++ .../02-legacy-reactive-statements.md | 87 ------------------- 3 files changed, 88 insertions(+), 88 deletions(-) create mode 100644 documentation/docs/99-legacy/02-legacy-reactive-assignments.md delete mode 100644 documentation/docs/99-legacy/02-legacy-reactive-statements.md diff --git a/documentation/docs/99-legacy/01-legacy-let.md b/documentation/docs/99-legacy/01-legacy-let.md index ad93e25b9e26..0d1a0a72bf11 100644 --- a/documentation/docs/99-legacy/01-legacy-let.md +++ b/documentation/docs/99-legacy/01-legacy-let.md @@ -1,5 +1,5 @@ --- -title: Reactive declarations +title: Reactive let/var declarations --- In runes mode, reactive state is explicitly declared with the [`$state` rune]($state). diff --git a/documentation/docs/99-legacy/02-legacy-reactive-assignments.md b/documentation/docs/99-legacy/02-legacy-reactive-assignments.md new file mode 100644 index 000000000000..5f7c9da79070 --- /dev/null +++ b/documentation/docs/99-legacy/02-legacy-reactive-assignments.md @@ -0,0 +1,87 @@ +--- +title: Reactive $: statements +--- + +In runes mode, reactions to state updates are handled with the [`$derived`]($derived) and [`$effect`]($effect) runes. + +In legacy mode, any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with a `$:` [label](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). These statements run after other code in the ` +``` + +Statements are ordered _topologically_ by their dependencies and their assignments: since the `console.log` statement depends on `sum`, `sum` is calculated first even though it appears later in the source. + +Multiple statements can be combined by putting them in a block: + +```js +// @noErrors +$: { + // recalculate `total` when `items` changes + total = 0; + + for (const item of items) { + total += item.value; + } +} +``` + +The left-hand side of a reactive assignments can be an identifier, or it can be a destructuring assignment: + +```js +// @noErrors +$: ({ larry, moe, curly } = stooges); +``` + +## Understanding dependencies + +The dependencies of a `$:` statement are determined at compile time — they are whichever variables are referenced (but not assigned to) inside the statement. + +In other words, a statement like this will _not_ re-run when `count` changes, because the compiler cannot 'see' the dependency: + +```js +// @noErrors +let count = 0; +let double = () => count * 2; + +$: doubled = double(); +``` + +Similarly, topological ordering will fail if dependencies are referenced indirectly: `z` will never update, because `y` is not considered 'dirty' when the update occurs. Moving `$: z = y` below `$: setY(x)` will fix it: + +```svelte + +``` + +## Browser-only code + +Reactive statements run during server-side rendering as well as in the browser. This means that any code that should only run in the browser must be wrapped in an `if` block: + +```js +// @noErrors +$: if (browser) { + document.title = title; +} +``` diff --git a/documentation/docs/99-legacy/02-legacy-reactive-statements.md b/documentation/docs/99-legacy/02-legacy-reactive-statements.md deleted file mode 100644 index bbf14a7241a0..000000000000 --- a/documentation/docs/99-legacy/02-legacy-reactive-statements.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: $: ---- - -Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run after other script code and before the component markup is rendered, whenever the values that they depend on have changed. - -```svelte - -``` - -Only values which directly appear within the `$:` block will become dependencies of the reactive statement. For example, in the code below `total` will only update when `x` changes, but not `y`. - -```svelte - - - -Total: {total} - - - -``` - -It is important to note that the reactive blocks are ordered via simple static analysis at compile time, and all the compiler looks at are the variables that are assigned to and used within the block itself, not in any functions called by them. This means that `yDependent` will not be updated when `x` is updated in the following example: - -```svelte - - -``` - -Moving the line `$: yDependent = y` below `$: setY(x)` will cause `yDependent` to be updated when `x` is updated. - -If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf. - -```svelte - - -``` - -> [!NOTE] -> In Svelte 5+, reactions are handled via the [`$derived`]($derived) and [`$effect`]($effect) runes From b639581ed778fd872bc148152a8b7f776418f87b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 21 Oct 2024 22:12:20 -0400 Subject: [PATCH 5/8] tweaks --- .../03-template-syntax/01-basic-markup.md | 4 +- .../docs/99-legacy/03-legacy-export-let.md | 51 +++++++++++-------- .../04-legacy-$$props-and-$$restProps.md | 30 +++++++++++ .../docs/99-legacy/04-legacy-$$props.md | 12 ----- .../docs/99-legacy/05-legacy-$$restProps.md | 12 ----- 5 files changed, 63 insertions(+), 46 deletions(-) create mode 100644 documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md delete mode 100644 documentation/docs/99-legacy/04-legacy-$$props.md delete mode 100644 documentation/docs/99-legacy/05-legacy-$$restProps.md diff --git a/documentation/docs/03-template-syntax/01-basic-markup.md b/documentation/docs/03-template-syntax/01-basic-markup.md index 07b093df878c..774ac6ca3e7e 100644 --- a/documentation/docs/03-template-syntax/01-basic-markup.md +++ b/documentation/docs/03-template-syntax/01-basic-markup.md @@ -18,7 +18,7 @@ A lowercase tag, like `
`, denotes a regular HTML element. A capitalised tag
``` -## Attributes and props +## Element attributes By default, attributes work exactly like their HTML counterparts. @@ -72,6 +72,8 @@ When the attribute name and value match (`name={name}`), they can be replaced wi --> ``` +## Component props + By convention, values passed to components are referred to as _properties_ or _props_ rather than _attributes_, which are a feature of the DOM. As with elements, `name={name}` can be replaced with the `{name}` shorthand. diff --git a/documentation/docs/99-legacy/03-legacy-export-let.md b/documentation/docs/99-legacy/03-legacy-export-let.md index 75ff14d4e135..877e105b1fa2 100644 --- a/documentation/docs/99-legacy/03-legacy-export-let.md +++ b/documentation/docs/99-legacy/03-legacy-export-let.md @@ -2,11 +2,14 @@ title: export let --- -Svelte uses the `export` keyword to mark a variable declaration as a _property_ or _prop_, which means it becomes accessible to consumers of the component (see the section on [attributes and props](/docs/basic-markup#attributes-and-props) for more information). +In runes mode, [component props](basic-markup#Component-props) are declared with the [`$props`]($props) rune, allowing parent components to pass in data. + +In legacy mode, props are marked with the `export` keyword, and can have a default value: ```svelte ``` -You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is `undefined`) when instantiating the component. Note that if the values of props are subsequently updated, then any prop whose value is not specified will be set to `undefined` (rather than its initial value). +The default value is used if it would otherwise be `undefined` when the component is created. -In development mode (see the [compiler options](/docs/svelte-compiler#compile)), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is `undefined`. +> [!NOTE] Unlike in runes mode, if the parent component changes a prop from a defined value to `undefined`, it does not revert to the initial value. -```svelte - +Props without default values are considered _required_, and Svelte will print a warning during development if no value is provided, which you can squelch by specifying `undefined` as the default value: + +```js +export let foo +++= undefined;+++ ``` -If you export a `const`, `class` or `function`, it is readonly from outside the component. Functions are valid prop values, however, as shown below. +## Component exports + +An exported `const`, `class` or `function` declaration is _not_ considered a prop — instead, it becomes part of the component's API: ```svelte - + +``` + +```svelte + + + + + + ``` -Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs/component-directives#bind-this). +## Renaming props -You can use reserved words as prop names. +The `export` keyword can appear separately from the declaration. This is useful for renaming props, for example in the case of a reserved word: ```svelte @@ -58,6 +70,3 @@ You can use reserved words as prop names. export { className as class }; ``` - -> [!NOTE] -> In Svelte 5+, use the [`$props`]($props) rune instead diff --git a/documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md b/documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md new file mode 100644 index 000000000000..33cac97035af --- /dev/null +++ b/documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md @@ -0,0 +1,30 @@ +--- +title: $$props and $$restProps +--- + +In runes mode, getting an object containing all the props that were passed in is easy, using the [`$props`]($props) rune. + +In legacy mode, we use `$$props` and `$$restProps`: + +- `$$props` contains all the props that were passed in, including ones that are not individually declared with the `export` keyword +- `$$restProps` contains all the props that were passed in _except_ the ones that were individually declared + +For example, a ` + + +``` + +In Svelte 3/4 using `$$props` and `$$restProps` creates a modest performance penalty, so they should only be used when needed. diff --git a/documentation/docs/99-legacy/04-legacy-$$props.md b/documentation/docs/99-legacy/04-legacy-$$props.md deleted file mode 100644 index 32f64287f0f4..000000000000 --- a/documentation/docs/99-legacy/04-legacy-$$props.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: $$props ---- - -`$$props` references all props that are passed to a component, including ones that are not declared with `export`. Using `$$props` will not perform as well as references to a specific prop because changes to any prop will cause Svelte to recheck all usages of `$$props`. But it can be useful in some cases – for example, when you don't know at compile time what props might be passed to a component. - -```svelte - -``` - -> [!NOTE] -> In Svelte 5+, this concept is unnecessary as you can use [`let prop = $props()`]($props) instead diff --git a/documentation/docs/99-legacy/05-legacy-$$restProps.md b/documentation/docs/99-legacy/05-legacy-$$restProps.md deleted file mode 100644 index db84a9103056..000000000000 --- a/documentation/docs/99-legacy/05-legacy-$$restProps.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: $$restProps ---- - -`$$restProps` contains only the props which are _not_ declared with `export`. It can be used to pass down other unknown attributes to an element in a component. It shares the same performance characteristics compared to specific property access as `$$props`. - -```svelte - -``` - -> [!NOTE] -> In Svelte 5+, this concept is unnecessary as you can use [`let { foo, ...rest } = $props()`]($props) instead From c0fbb24ecbd2bac92c6f9f9bc89c9dac17cdf944 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 21 Oct 2024 22:33:00 -0400 Subject: [PATCH 6/8] tweaks --- documentation/docs/99-legacy/10-legacy-on.md | 79 +++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/documentation/docs/99-legacy/10-legacy-on.md b/documentation/docs/99-legacy/10-legacy-on.md index 9584a9aa707e..f2ee694cc1e0 100644 --- a/documentation/docs/99-legacy/10-legacy-on.md +++ b/documentation/docs/99-legacy/10-legacy-on.md @@ -2,17 +2,9 @@ title: on: --- -```svelte - -on:eventname={handler} -``` - -```svelte - -on:eventname|modifiers={handler} -``` +In runes mode, event handlers are just like any other attribute or prop. -Use the `on:` directive to listen to DOM events. +In legacy mode, we use the `on:` directive: ```svelte @@ -30,7 +22,7 @@ Use the `on:` directive to listen to DOM events. ``` -Handlers can be declared inline with no performance penalty. As with attributes, directive values may be quoted for the sake of syntax highlighters. +Handlers can be declared inline with no performance penalty: ```svelte ``` -Add _modifiers_ to DOM events with the `|` character. +Add _modifiers_ to element event handlers with the `|` character. ```svelte
@@ -64,7 +56,9 @@ Modifiers can be chained together, e.g. `on:click|once|capture={...}`. If the `on:` directive is used without a value, the component will _forward_ the event, meaning that a consumer of the component can listen for it. ```svelte - + ``` It's possible to have multiple event listeners for the same event: @@ -72,58 +66,71 @@ It's possible to have multiple event listeners for the same event: ```svelte - + ``` -> [!NOTE] -> In Svelte 5+, use event attributes instead -> ```svelte -> -> ``` - ## Component events -Component events created with [`createEventDispatcher`](svelte#createEventDispatcher) create a `CustomEvent`. These events do not bubble. The detail argument corresponds to the `CustomEvent.detail` property and can contain any type of data. +Components can dispatch events by creating a _dispatcher_ when they are initialised: ```svelte + - + + ``` -Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object. +`dispatch` creates a [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). If a second argument is provided, it becomes the `detail` property of the event object. + +A consumer of this component can listen for the dispatched events: ```svelte - + n -= 1} + on:increment={() => n += 1} +/> + +

n: {n}

``` +Component events do not bubble — a parent component can only listen for events on its immediate children. + +Other than `once`, modifiers are not valid on component event handlers. + > [!NOTE] -> If you're planning on migrating to Svelte 5, use callback props instead. This will make upgrading easier as `createEventDispatcher` is deprecated +> If you're planning an eventual migration to Svelte 5, use callback props instead. This will make upgrading easier as `createEventDispatcher` is deprecated: +> > ```svelte +> > -> -> +> +> +> > ``` From d6f461804051603f9b7be6792c361b41580d4233 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 21 Oct 2024 23:21:22 -0400 Subject: [PATCH 7/8] tweaks --- .../docs/99-legacy/20-legacy-slots.md | 108 ++++++++---------- .../docs/99-legacy/21-legacy-$$slots.md | 15 ++- .../99-legacy/22-legacy-svelte-fragment.md | 10 +- .../99-legacy/30-legacy-svelte-component.md | 22 +--- .../docs/99-legacy/31-legacy-svelte-self.md | 4 +- .../docs/99-legacy/40-legacy-component-api.md | 4 +- 6 files changed, 74 insertions(+), 89 deletions(-) diff --git a/documentation/docs/99-legacy/20-legacy-slots.md b/documentation/docs/99-legacy/20-legacy-slots.md index a82d8435bff0..5189f2017db8 100644 --- a/documentation/docs/99-legacy/20-legacy-slots.md +++ b/documentation/docs/99-legacy/20-legacy-slots.md @@ -2,85 +2,75 @@ title: --- -```svelte - -``` +In Svelte 5, content can be passed to components in the form of [snippets](snippet) and rendered using [render tags](@render). -```svelte - -``` +In legacy mode, content inside component tags is considered _slotted content_, which can be rendered by the component using a `` element: ```svelte - -``` - -Components can have child content, in the same way that elements can. + + -The content is exposed in the child component using the `` element, which can contain fallback content that is rendered if no children are provided. +This is some slotted content +``` ```svelte - -
- - this fallback content will be rendered when no content is provided, like in the first example - + + - - - - - - -

this is some child content that will overwrite the default slot content

-
``` -Note: If you want to render regular `` element, You can use ``. - -> [!NOTE] -> In Svelte 5+, use snippets instead +> [!NOTE] If you want to render a regular `` element, you can use ``. -## `` +## Named slots -Named slots allow consumers to target specific areas. They can also have fallback content. +A component can have _named_ slots in addition to the default slot. On the parent side, add a `slot="..."` attribute to an element, component or [``](legacy-svelte-fragment) directly inside the component tags. ```svelte - -
- No header was provided -

Some content between header and footer

- -
- - - -

Hello

-

Copyright (c) 2019 Svelte Industries

-
+ + + +{#if open} + + This is some slotted content + + +++
+++ + + +++
+++ +
+{/if} ``` -Components can be placed in a named slot using the syntax ``. -In order to place content in a slot without using a wrapper element, you can use the special element ``. +On the child side, add a corresponding `` element: ```svelte - -
- No header was provided -

Some content between header and footer

- + + +``` - - - - -

All rights reserved.

-

Copyright (c) 2019 Svelte Industries

-
-
+## Fallback content + +If no slotted content is provided, a component can define fallback content by putting it inside the `` element: + +```svelte + + This will be rendered if no slotted content is provided + ``` -## `` +## Passing data to slotted content Slots can be rendered zero or more times and can pass values _back_ to the parent using props. The parent exposes the values to the slot template using the `let:` directive. @@ -122,3 +112,5 @@ Named slots can also expose values. The `let:` directive goes on the element wit

Copyright (c) 2019 Svelte Industries

``` + + diff --git a/documentation/docs/99-legacy/21-legacy-$$slots.md b/documentation/docs/99-legacy/21-legacy-$$slots.md index ad5fce6c801c..7ca1cef8445a 100644 --- a/documentation/docs/99-legacy/21-legacy-$$slots.md +++ b/documentation/docs/99-legacy/21-legacy-$$slots.md @@ -2,27 +2,26 @@ title: $$slots --- -`$$slots` is an object whose keys are the names of the slots passed into the component by the parent. If the parent does not pass in a slot with a particular name, that name will not be present in `$$slots`. This allows components to render a slot (and other elements, like wrappers for styling) only if the parent provides it. +In runes mode, we know which [snippets](snippet) were provided to a component, as they're just normal props. -Note that explicitly passing in an empty named slot will add that slot's name to `$$slots`. For example, if a parent passes `
` to a child component, `$$slots.title` will be truthy within the child. +In legacy mode, the way to know if content was provided for a given slot is with the `$$slots` object, whose keys are the names of the slots passed into the component by the parent. ```svelte - +
{#if $$slots.description} - +
{/if}
+``` - +```svelte +

Blog Post Title

``` - -> [!NOTE] -> In Svelte 5+, this concept is obsolete, as you pass snippets as component props and can check whether or not that prop is set diff --git a/documentation/docs/99-legacy/22-legacy-svelte-fragment.md b/documentation/docs/99-legacy/22-legacy-svelte-fragment.md index 99fe192f5a56..8827ab53cba5 100644 --- a/documentation/docs/99-legacy/22-legacy-svelte-fragment.md +++ b/documentation/docs/99-legacy/22-legacy-svelte-fragment.md @@ -5,14 +5,20 @@ title: The `` element allows you to place content in a [named slot](/docs/special-elements#slot-slot-name-name) without wrapping it in a container DOM element. This keeps the flow layout of your document intact. ```svelte - +
No header was provided

Some content between header and footer

+``` + +```svelte + + -

Hello

diff --git a/documentation/docs/99-legacy/30-legacy-svelte-component.md b/documentation/docs/99-legacy/30-legacy-svelte-component.md index 2c04238f2d56..5d385a9c0278 100644 --- a/documentation/docs/99-legacy/30-legacy-svelte-component.md +++ b/documentation/docs/99-legacy/30-legacy-svelte-component.md @@ -2,26 +2,12 @@ title: --- -```svelte - -``` +In runes mode, `` will re-render if the value of `MyComponent` changes. -The `` element renders a component dynamically, using the component constructor specified as the `this` property. When the property changes, the component is destroyed and recreated. - -If `this` is falsy, no component is rendered. +In legacy mode, it won't — we must use ``, which destroys and recreates the component instance when the value of its `this` expression changes: ```svelte - + ``` -> [!NOTE] -> In Svelte 5+, this concept is obsolete, as you can just reference `$state` or `$derived` variables containing components -> ```svelte -> -> -> -> -> -> ``` +If `this` is falsy, no component is rendered. diff --git a/documentation/docs/99-legacy/31-legacy-svelte-self.md b/documentation/docs/99-legacy/31-legacy-svelte-self.md index b601eae62aa3..bfd140ac49dc 100644 --- a/documentation/docs/99-legacy/31-legacy-svelte-self.md +++ b/documentation/docs/99-legacy/31-legacy-svelte-self.md @@ -20,14 +20,14 @@ It cannot appear at the top level of your markup; it must be inside an if or eac ``` > [!NOTE] -> This concept is obsolete, as you can just self-import components +> This concept is obsolete, as components can import themselves: > ```svelte > > -> +> > {#if count > 0} >

counting down... {count}

> diff --git a/documentation/docs/99-legacy/40-legacy-component-api.md b/documentation/docs/99-legacy/40-legacy-component-api.md index 26b3a310714d..5bbe7e72374d 100644 --- a/documentation/docs/99-legacy/40-legacy-component-api.md +++ b/documentation/docs/99-legacy/40-legacy-component-api.md @@ -2,6 +2,8 @@ title: Imperative component API --- +In Svelte 3 and 4, the API for interacting with a component is different than in Svelte 5. Note that this page does _not_ apply to legacy mode components in a Svelte 5 application. + ## Creating a component ```ts @@ -156,7 +158,7 @@ Unlike client-side components, server-side components don't have a lifespan afte A server-side component exposes a `render` method that can be called with optional props. It returns an object with `head`, `html`, and `css` properties, where `head` contains the contents of any `` elements encountered. -You can import a Svelte component directly into Node using [`svelte/register`](/docs/svelte-register). +You can import a Svelte component directly into Node using `svelte/register`. ```js // @noErrors From f3d4380875a9762269c41962c11f464a7d5cb394 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 21 Oct 2024 23:30:26 -0400 Subject: [PATCH 8/8] fix link --- documentation/docs/07-misc/04-custom-elements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/07-misc/04-custom-elements.md b/documentation/docs/07-misc/04-custom-elements.md index 39659f1950b5..48e1d1f6984c 100644 --- a/documentation/docs/07-misc/04-custom-elements.md +++ b/documentation/docs/07-misc/04-custom-elements.md @@ -36,7 +36,7 @@ document.body.innerHTML = ` `; ``` -Any [props](basic-markup#Attributes-and-props) are exposed as properties of the DOM element (as well as being readable/writable as attributes, where possible). +Any [props](basic-markup#Component-props) are exposed as properties of the DOM element (as well as being readable/writable as attributes, where possible). ```js // @noErrors