Skip to content

Commit

Permalink
docs: Svelte docs (#41)
Browse files Browse the repository at this point in the history
* overview

* getting started

* component fundamentals

* basic markup

* control flow

* snippets

* styles and classes

* transitions and animations (WIP, needs motion and tweened, reference should have more details so we can point to it)

* actions WIP (add $effect)

* bindings

* special elements

* data fetching (WIP, what else can we put there?)

* stores

* imperative component api

* reactivity fundamentals

* contex

* lifecycle hooks

* state

* debugging

* fix

* more details on $state.is, closes sveltejs/svelte#12167

* side effects

* typescript

related: sveltejs/svelte#11502

* custom elements

* events
  • Loading branch information
dummdidumm authored Jun 25, 2024
1 parent cbad133 commit fd8b212
Show file tree
Hide file tree
Showing 23 changed files with 3,860 additions and 9 deletions.
23 changes: 19 additions & 4 deletions apps/svelte.dev/content/docs/svelte/01-introduction/01-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,25 @@ title: Overview
- A few code examples to have a very rough understanding of how Svelte code looks like
- Jump off points to tutorial, SvelteKit etc

## One
Svelte is a web UI framework that uses a compiler to turn declarative component code like this...

TODO
```svelte
<!--- file: App.svelte --->
<script lang="ts">
let count = $state(0);
## Two
function increment() {
count += 1;
}
</script>
TODO
<button onclick={increment}>
clicks: {count}
</button>
```

...into tightly optimized JavaScript that updates the document when state like count changes. Because the compiler can 'see' where count is referenced, the generated code is highly efficient, and because we're hijacking syntax like `$state(...)` and `=` instead of using cumbersome APIs, you can write less code.

Besides being fun to work with, Svelte offers a lot of features built-in, such as animations and transitions. Once you've written your first components you can reach for our batteries included metaframework [SvelteKit](/docs/kit) which provides you with an opinionated router, data loading and more.

If you're new to Svelte, visit the [interactive tutorial](/tutorial) before consulting this documentation. You can try Svelte online using the [REPL](/repl). Alternatively, if you'd like a more fully-featured environment, you can try Svelte on [StackBlitz](https://sveltekit.new).
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,34 @@ title: Getting started
- `npm create vite@latest`, describe that it scaffolds Svelte SPA powered by Vite
- mention `svelte-add`
- Jump off points to tutorial, SvelteKit etc

## Start a new project

We recommend using [SvelteKit](https://kit.svelte.dev/), the official application framework from the Svelte team:

```
npm create svelte@latest myapp
cd myapp
npm install
npm run dev
```

SvelteKit will handle calling [the Svelte compiler](https://www.npmjs.com/package/svelte) to convert your `.svelte` files into `.js` files that create the DOM and `.css` files that style it. It also provides all the other pieces you need to build a web application such as a development server, routing, deployment, and SSR support. [SvelteKit](https://kit.svelte.dev/) uses [Vite](https://vitejs.dev/) to build your code.

Don't worry if you don't know Svelte yet! You can ignore all the nice features SvelteKit brings on top for now and dive into it later.

### Alternatives to SvelteKit

If you don't want to use SvelteKit for some reason, you can also use Svelte with Vite (but without SvelteKit) by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory thanks using [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you will probably need to [choose a routing library](faq#is-there-a-router) as well.

Alternatively, there are plugins for [Rollup](https://github.com/sveltejs/rollup-plugin-svelte), [Webpack](https://github.com/sveltejs/svelte-loader) [and a few others](https://sveltesociety.dev/packages?category=build-plugins) to handle Svelte compilation — which will output `.js` and `.css` that you can insert into your HTML — but setting up SSR with them requires more manual work.

## Editor tooling

The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and there are integrations with various other [editors](https://sveltesociety.dev/resources#editor-support) and tools as well.

You can also check your code from the command line using [svelte-check](https://www.npmjs.com/package/svelte-check) (using the Svelte or Vite CLI setup will install this for you).

## Getting help

Don't be shy about asking for help in the [Discord chatroom](https://svelte.dev/chat)! You can also find answers on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte).
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: Reactivity fundamentals
---

Reactivity is at the heart of interactive UIs. When you click a button, you expect some kind of response. It's your job as a developer to make this happen. It's Svelte's job to make your job as intuitive as possible, by providing a good API to express reactive systems.

## Runes

Svelte 5 uses _runes_, a powerful set of primitives for controlling reactivity inside your Svelte components and inside `.svelte.js` and `.svelte.ts` modules.

Runes are function-like symbols that provide instructions to the Svelte compiler. You don't need to import them from anywhere — when you use Svelte, they're part of the language.

The following sections introduce the most important runes for declare state, derived state and side effects at a high level. For more details refer to the later sections on [state](/docs/svelte/runes/state) and [side effects](/docs/svelte/runes/side-effects).

## `$state`

Reactive state is declared with the `$state` rune:

```svelte
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
clicks: {count}
</button>
```

You can also use `$state` in class fields (whether public or private):

```js
// @errors: 7006 2554
class Todo {
done = $state(false);
text = $state();

constructor(text) {
this.text = text;
}
}
```

## `$derived`

Derived state is declared with the `$derived` rune:

```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>
{doubled}
</button>
<p>{count} doubled is {doubled}</p>
```

The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions.

As with `$state`, you can mark class fields as `$derived`.

## `$effect`

To run _side-effects_ when the component is mounted to the DOM, and when values change, we can use the `$effect` rune ([demo](/#H4sIAAAAAAAAE31T24rbMBD9lUG7kAQ2sbdlX7xOYNk_aB_rQhRpbAsU2UiTW0P-vbrYubSlYGzmzMzROTPymdVKo2PFjzMzfIusYB99z14YnfoQuD1qQh-7bmdFQEonrOppVZmKNBI49QthCc-OOOH0LZ-9jxnR6c7eUpOnuv6KeT5JFdcqbvbcBcgDz1jXKGg6ncFyBedYR6IzLrAZwiN5vtSxaJA-EzadfJEjKw11C6GR22-BLH8B_wxdByWpvUYtqqal2XB6RVkG1CoHB6U1WJzbnYFDiwb3aGEdDa3Bm1oH12sQLTcNPp7r56m_00mHocSG97_zd7ICUXonA5fwKbPbkE2ZtMJGGVkEdctzQi4QzSwr9prnFYNk5hpmqVuqPQjNnfOJoMF22lUsrq_UfIN6lfSVyvQ7grB3X2mjMZYO3XO9w-U5iLx42qg29md3BP_ni5P4gy9ikTBlHxjLzAtPDlyYZmRdjAbGq7HprEQ7p64v4LU_guu0kvAkhBim3nMplWl8FreQD-CW20aZR0wq12t-KqDWeBywhvexKC3memmDwlHAv9q4Vo2ZK8KtK0CgX7u9J8wXbzdKv-nRnfF_2baTqlYoWUF2h5efl9-n0O6koAMAAA==)):

```svelte
<script>
let size = $state(50);
let color = $state('#ff3e00');
let canvas;
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` or `size` change
context.fillStyle = color;
context.fillRect(0, 0, size, size);
});
</script>
<canvas bind:this={canvas} width="100" height="100" />
```

The function passed to `$effect` will run when the component mounts, and will re-run after any changes to the values it reads that were declared with `$state` or `$derived` (including those passed in with `$props`). Re-runs are batched (i.e. changing `color` and `size` in the same moment won't cause two separate runs), and happen after any DOM updates have been applied.
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,181 @@ title: Component fundamentals

- script (module) / template / style (rough overview)
- `$props` / `$state` (in the context of components)

Components are the building blocks of Svelte applications. They are written into `.svelte` files, using a superset of HTML.

All three sections — script, styles and markup — are optional.

```svelte
<script>
// logic goes here
</script>
<!-- markup (zero or more items) goes here -->
<style>
/* styles go here */
</style>
```

## &lt;script&gt;

A `<script>` block contains JavaScript (or TypeScript, when adding the `lang="ts"` attribute) that runs when a component instance is created. Variables declared (or imported) at the top level are 'visible' from the component's markup.

### Public API of a component

Svelte uses the `$props` rune to declare _properties_ or _props_, which means describing the public interface of the component which becomes accessible to consumers of the component.

> `$props` is one of several runes, which are special hints for Svelte's compiler to make things reactive.
```svelte
<script>
let { foo, bar, baz } = $props();
// Values that are passed in as props
// are immediately available
console.log({ foo, bar, baz });
</script>
```

You can specify a fallback value for a prop. It will be used if the component's consumer doesn't specify the prop on the component when instantiating the component, or if the passed value is `undefined` at some point.

```svelte
<script>
let { foo = 'optional default initial value' } = $props();
</script>
```

To get all properties, use rest syntax:

```svelte
<script>
let { a, b, c, ...everythingElse } = $props();
</script>
```

You can use reserved words as prop names.

```svelte
<script>
// creates a `class` property, even
// though it is a reserved word
let { class: className } = $props();
</script>
```

If you're using TypeScript, you can declare the prop types:

```svelte
<script lang="ts">
interface Props {
a: number;
b: boolean;
c: string;
[key: string]: unknown;
}
let { a, b, c, ...everythingElse }: Props = $props();
</script>
```

If you export a `const`, `class` or `function`, it is readonly from outside the component.

```svelte
<script>
export const thisIs = 'readonly';
export function greet(name) {
alert(`hello ${name}!`);
}
</script>
```

Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs/component-directives#bind-this).

### Reactive variables

To change component state and trigger a re-render, just assign to a locally declared variable that was declared using the `$state` rune.

Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect.

```svelte
<script>
let count = $state(0);
function handleClick() {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
```

Svelte's `<script>` blocks are run only when the component is created, so assignments within a `<script>` block are not automatically run again when a prop updates.

```svelte
<script>
let { person } = $props();
// this will only set `name` on component creation
// it will not update when `person` does
let { name } = person;
</script>
```

If you'd like to react to changes to a prop, use the `$derived` or `$effect` runes instead.

```svelte
<script>
let count = $state(0);
let double = $derived(count * 2);
$effect(() => {
if (count > 10) {
alert('Too high!');
}
});
</script>
```

For more information on reactivity, read the documentation around runes.

## &lt;script context="module"&gt;

A `<script>` tag with a `context="module"` attribute runs once when the module first evaluates, rather than for each component instance. Values declared in this block are accessible from a regular `<script>` (and the component markup) but not vice versa.

You can `export` bindings from this block, and they will become exports of the compiled module.

You cannot `export default`, since the default export is the component itself.

```svelte
<script context="module">
let totalComponents = 0;
// the export keyword allows this function to imported with e.g.
// `import Example, { alertTotal } from './Example.svelte'`
export function alertTotal() {
alert(totalComponents);
}
</script>
<script>
totalComponents += 1;
console.log(`total number of times this component has been created: ${totalComponents}`);
</script>
```

## &lt;style&gt;

CSS inside a `<style>` block will be scoped to that component.

```svelte
<style>
p {
/* this will only affect <p> elements in this component */
color: burlywood;
}
</style>
```

For more information regarding styling, read the documentation around [styles and classes](styles-and-classes).
Loading

0 comments on commit fd8b212

Please sign in to comment.