Pull to refresh

Как я переписал свой проект на Svelte

Level of difficultyEasy
Reading time6 min
Views8K

Приветствую всех. Уже как неделю я переписываю свой проект, который был на Vue options api с использованием Quasar и перевожу его на Svelte-Sveltkit-DaisyUI. Скажу сразу, он мне очень понравился, особенно в если учитывать что Vue composition api стал больше похож на React, нежели чем на самого себя. Складывается впечатление что Svelte это то к чему должен был прийти Vue, но он пришел к реакту (ты должен был бороться...).

Итак, тот код, который я писал на вью(вуй в простонародье) 10 месяцев на свелт был написан за 9 дней, и то успел добавить дополнительные функции. Кое-что еще не реализовано, но это легкая часть, которая займет дня 3-4, не больше. Затем привязка к бэкенду и тестирование и через 2-3 недели все должно быть в целом готово. Справедливости ради стоит отметить что не все время из этих 10 месяцев было использовано на написание кода. Половина времени было потрачено на безрезультатные попытки (пытки) написать бэкенд самому. Прыгал с одной технологии на другую, но в основном пытался(пытал себя) написать на фшарп. Ничего не вышло, перешел на ноду-экспресс. Кое-что вышло, но в процессе написания понял что бэк не мое. Один бэкендер говорил что работа бэкендера это как 8 часов решать "судоку" на работе, а в остальное время решать судоку для отдыха :-). Полностью с этим согласен. Главное что вовремя осознал свою неспособность писать бэкенд, а заодно и нелюбовь решать судоку. Хотя когда был в школе любил, вероятно и бэк в то время зашел бы, но не факт. Отныне, если когда-нибудь я буду писать бэк для чего-то, то буду использовать лишь готовые вещи вроде strapi или directus.

Также стоит отметить что при переписывании у меня уже был опыт и код от проекта на вью. Но на свелт все было бы быстрее даже несмотря на это, ибо свелт имеет многие киллер фичи которые вью либо убрал, либо не имел, также краткость и лаконичность синтаксиса и обилие простого сахара.

Здесь перечислю те киллер фичи которые есть у Svelte, но которые нет Vue, либо оно неудобно.

Изменение props

Самая главная фича лично для меня это способность изменять пропсы компонента. Это то чего мне не хватало у вью и то почему я не перешел на композишн апи(не только из за того что он похож на реакт). Вью опшнс апи хоть и запрещал менять пропсы, но по ссылке объекта или массива в пропсах можно было менять его свойства и получать реактивность при изменении чего-либо. Хотя все еще нельзя изменять проспы по имени переменной во вью, это очень сильно сокрощало мой код.

Свелт дает два вида передачи пропсов и один из них, как вы догадались, позволяет изменять пропсы несмотря ни на что, будь то объект, массив, или переменная с простым типом вроде строки.

<script>
  import Component from "./Component.svelte"
  const name = 'John Smithf'
  let count = 0;
  let config = {
    width: 10,
    height: 20,
    top: 0,
    left: 0
  }
</script>
<Component
           bind:count
           bind:config
           {name}>
  
<!--   Component.svelte -->
  <script>
  export let name;//Это неизменяемый пропс
  export let count, config;//Этих двоих уже можно изменить, и в родителе они тоже изменятся
  let increment = () => {
    count++
  }
  let changeConfig = () => {
    //Some code
  }
  </script>
  <h1>{name}</h1>
  <button on:click={increment}>{count}</button>

Не знаю как вам, но в каждом проекте я сталкивался с необходимостью менять пропс. С вью код получался просто ужасным, нечитаемым и большим. Я боялся что этот код смогу прочитать только я, однако с легким синтаксисом свелт это уже не проблема.

Также с добавлением изменяемых пропсов теперь я могу разделять свой многотонный код на еще больше компонентов, где каждый отвечает за свое. И никакой тайпскрипт не нужен. Честно, ненавижу тайпскрипт. Согласен, в команде тайпскрипт может принести некоторую пользу, но для одиночки это приносит лишь муки и снижение скорости разработки.

UseEffect

В реакте есть чудо юзэффект. У вью тоже есть computed, но почему то именно в моем коде мне приходилось всяческий изощряться чтобы заставить его работать. Он не хотел понимать что надо делать(или просто не хотел делать). Со свелтом такого нет. И в отличие от реактовского юзэффекта здесь не нужно указывать на изменение какой переменной реагировать. Компилятор сам смотрит и анализирует.

<script>
let count = 0;
let count2 = 0;
let sqr;
$: sqr = count * count; //Реагирует когда count меняется
$: sqr = count + count2; //Этот уже реагирует когда один из двух коунтов меняется. Нет нужды указывать за каким следить
 </script>
  

Это уменьшило мой код, который было на вью просто в разы.

Each вместо v-for :key

Есть самый главный минус свелт, воистину то что было во вью. Это способность - "киллер"-фича во вью можно передать в vFor в качестве итерируемого объект или просто число <div v-for="digit in 5" :key="digit" /> и это работало. И я удивился когда не смог сделать этого в свелт.

Ну ок. Возможно никто кроме меня и не использовал никогда эту фичу, а может и да. В любом случае можно легко заменить на Object.keys или .entries и [0,1,2,3,4,5].

{#each Object.entries as [name, value], id}
<div>{id} {name} : {value}</div>
{/each}

{#each [0,1,2,3,4,5] as value, id}
<div>{id} {value}</div>
{/each}

Так я все-таки научился чему-то у курсов Шемседдинова))) Надо будет добить)))

If-elseIf-else, await, store, events

Ну тут думаю нет нужды перечислять все это. Итак ясно что if это аналог v-if из вью. Ну а с await я еще не работал, хотя итак понятно что он делает. Буду надеяться что он также удобен как и все остальное. Стоит отметить что выделение логических элементов в отдельные тэгоподобия сделало код более читаемым, нежели чем аттрибутка у вью.

Сторы ничем от реактовского не отличаются, но синтаксис делает их использование одним удовольствием.

События во вью требовали явной передачи $event-а, но свелт передает этот параметр по умолчанию, и требует явной передачи лишь когда есть другие параметры.

<script>
  let handleClick = (ev) => {
    console.log(ev)
  }
  let handleClickWithParams = (ev, param) => {
    console.log(ev, param)
  }
</script>
<button on:click={handleClick}>Click</button>
<button on:click={ev=>handleClickWithParams(ev, param)}>handleClickWithParams</button>

Эмиты же событий из компонента в парент я не использовал. Поначалу из за незнания пришлось на них писать, но с осознанием всего перечисленного я просто удалил их за ненадобностью, иначе они мусорили код. Серьезно, с мощью всего перечисленного я не увидел где могу использовать их в моем коде, хотя такие задачи несомненно есть.

Special elements

В свелт есть дополнительные плюшки в виде элементов window, head, body и др., к которым из компонента можно добраться только через дом. Эти элементы позволяют менять их аттрибуты прямо из компонента или странички.

<svelte:head>
  <title>Главная</title>
</svelte:head>

Хотя есть элементы, которых нет, или фич которые обещали подвести, такие как <svelte:html> для того чтобы динамический менять lang или data-theme атрибуты, как сказано здесь. Или возможность добавлять html-элементы прямо внутрь <svelte:body> элемента как просят здесь. В целом это все очень помогает.

Работа с DOM и onMount

В свелт есть основные хуки, но они не очень нужны. На вью я постоянно использовал onMount, однако в свелт код и так запускается самостоятельно и нет необходимости использовать хуки без особой надобности. OnMount может быть полезен если нужно работать с DOM. Так как SveltKit по умолчанию SSR, то мой код где я хотел обратиться к document или window сломался. Я нашел два выхода. Первое - onMount, так как он запускается только в браузере то имеет все объекты. Но я отмел этот способ за неудобностью его.

Второй способ это проверить есть ли вообще эти объекты. Но if(document), if(window) все равно вызывали ошибки. Выход был найден

<script>
  import { browser } from '$app/environment';
  let elem;
  if(browser)elem = document.getElementById();//Some code

  $: if(browser)document.querySelector('.active').style.color = 'red';
</script>

Этот способ был найден мной наиболее удобным для моих задач.

Динамическая передача переменных в css

Работая с вью мне как-то понадобилось изменить css прямо в тэге <style> компонента. Сейчас это кажется бредом, но у свелт есть и это. Хотя данная фича мне нравится, но то что мне нужно сейчас она дать мне не смогла. А нужно мне динамический менять размер страницы при печати чтобы не задавать каждый раз при изменении конфига эти параметры вручную

<style>
  @media print{
    @page{
      size: var(--paper-format)//a3, a4, a5, landscape or portrait
    }
  }
</style>

Однако данный код ничего не изменил. Так что если есть такая функция в самом js, буду рад если поделитесь в комментах.

Ощущения

В целом мне все нравится. Если не учитывать одного хамоватого модератора в issues, то все гуд. Пока что прощай, Vue. Здравствуй, Svelte. Хотя если Эван на Vue 4 или 5-ом сделает все похожим на Svelte-SvelteKit, то посмотрим. Но лично мое мнение, было бы классно объединись Эван Ю и Рич Харрис над объединенным svuelte или svelvue. Хотя это может все испортить и сделать только хуже. Код проекта, к сожалению, не могу показать.

Tags:
Hubs:
Total votes 18: ↑6 and ↓12-6
Comments50

Articles