Svelte
Svelte - тонкий, стройный, изящный, элегантный
Основное преимущество Svelte - браузеру отдаётся уже скомпилированный код, за счёт чего обеспечивается его минимальный вес и максимальное быстродействие
За эту особенность Svelte называют исчезающим фреймворком - разработчик писал код пользуясь возможностями фреймворка, а браузер получил чистый JavaScript
Как и во vue, скрипты и стили пишутся внутри компонента Svelte. Отличие в том, что если в vue разметку заключали в тег template. в Svelte разметка пишется без любого ограничивающего тега. Что не скрипт и не стиль, то - разметка
Любые переменные, указанные в скрипте, могут отображаться в разметку. Для этого их достаточно взять в фигурные скобки
Базовый пример
<script>
let name = 'World'
</script>
<style>
h1 {
color: indigo;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
}
</style>
<main>
<h1>Hello {name}!</h1>
</main>
Как вставить html-разметку
<script>
let name = '<i>World</i>'
</script>
<main>
<h1>Hello {@html name}!</h1>
</main>
Как сделать стиль глобальным
Кроме как написать его в файле global.css, можно использовать директиву :global, которое указывает, что стили должны применяться глобально, а не только к текущему компоненту.
<style>
:global(h1) {
color: indigo;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
}
</style>
Добавление событий
Обработчики событий добавляются директивой on:, например, on:click.
<script>
let name = 'World'
const changeName = () => {
name === 'World' ? name = 'Svelte' : name = 'World';
}
</script>
<style>
h1 {
color: indigo;
}
</style>
<main>
<h1>Hello {name}!</h1>
<button on:click={changeName}>Change Name</button>
</main>
Обработчик перемещения курсора внутри блока
<script>
const getCursorPos = (event) => {
pos.x = event.x,
pos.y = event.y
}
</script>
<style>
.block {
width: 400px;
height: 300px;
margin: 0 auto;
border: 2px solid firebrick;
}
</style>
<main>
<div class="block" on:mousemove={getCursorPos}>
<h3>X: {pos.x}, Y: {pos.y}</h3>
</div>
</main>
У событий могут быть модификаторы, которые записываются через вертикальную черту
<button on:click|once={changeName}>Change Name</button>
<form on:submit|preventDefault ={handleSubmit}></form>
Реактивность
<script>
let name = 'World'
$: value = name;
</script>
<h1>Hello {value}!</h1>
$: value = name
Выражение $: является реактивным объявлением в Svelte.
Оно означает что Svelte будет отслеживать изменение переменной name и автоматически обновлять значение переменной value в соответствии с изменениями name.
Работа с формами bind:
<script>
let name = 'World'
$: value = name;
</script>
<main>
<h1>Hello {value}!</h1>
<input type="text" bind:value>
</main>
В коде выше мы отслеживаем изменение переменной value и привязали её значение к значению input.value
<script>
let name = 'World'
$: value = name;
</script>
<style>
.red {
border-color: red;
}
.green {
border-color: green;
}
input {
outline: 0;
}
</style>
<main>
<h1>Hello {name}!</h1>
<input type="text" bind:value>
</main>
Условные операторы if... else
<main>
<h1>Hello {name}!</h1>
<input type="text" bind:value>
{#if value.length > 5}
<p>Value length more than 5</p>
{:else if value.length < 5}
<p>Value length less than 5 </p>
{:else}
<p>Value length equal 5 </p>
{/if}
</main>
Условные классы
<script>
let name = 'World'
$: value = name;
$: error = isEven(value);
function isEven(value) {
return value.length % 2 === 0;
}
</script>
<style>
input {
outline: 0;
}
.red {
border-color: red;
}
.green {
border-color: green;
}
</style>
<main>
<h1>Hello {name}!</h1>
<input type="text" bind:value class:red={error} class:green={!error}>
</main>
Компоненты
В папке src создаём папку components, в ней создаём файл People.svelte
<script>
export let name = "Undefined name";
export let age = "Undefined age";
export let job = "Undefined job";
</script>
<style>
</style>
<div>
<h2>People name: {name}</h2>
<p>People age: {age}</p>
<p>People job: {job}</p>
</div>
Импортируем его в файл App.svelte
<script>
import People from "./components/People.svelte";
</script>
<main>
<People />
</main>
Передача пропсов в компоненты
<script>
import People from "./components/People.svelte";
const people = [
{id: 1, name: 'Oleg', age: 30, job: 'TeamLead'},
{id: 2, name: 'Jon', age: 22, job: 'Developer'},
{id: 3, name: 'Jane', age: 18, job: 'Student'}
]
</script>
<main>
<People name={people[0].name} age={people[0].age} job={people[0].job} />
<People {...people[1]} />
<People {...people[2]} />
</main>
Первый вариант приведён в качестве примера, второй и третий проще и удобнее
Итерация по массиву
<script>
import People from "./components/People.svelte";
const people = [
{id: 1, name: 'Oleg', age: 30, job: 'TeamLead'},
{id: 2, name: 'Jon', age: 22, job: 'Developer'},
{id: 3, name: 'Jane', age: 18, job: 'Student'}
]
</script>
<main>
{#each people as person}
<People {...person}/>
{/each}
</main>
Или так
<script>
import People from "./components/People.svelte";
const people = [
{id: 1, name: 'Oleg', age: 30, job: 'TeamLead'},
{id: 2, name: 'Jon', age: 22, job: 'Developer'},
{id: 3, name: 'Jane', age: 18, job: 'Student'}
]
</script>
<main>
{#each people as {name, age, job}}
<People {name} {age} {job}/>
{/each}
</main>