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>