Svelte

Svelte foydalanuvchi interfeyslarini yaratish uchun tubdan yangi bo’lgan yondashuvni taklif qiladi. An’anaviy freymvorklardan farqli o’laroq, Svelte sizning deklarativ komponentlaringizni samarali imperativ kodga aylantiruvchi kompilyator hisoblanadi va bu kod DOM’ni aniq yangilab turadi. Natijada, kamroq kod bilan yuqori samaradorlikka ega, reaktiv veb-ilovalarni yozish imkoniyatiga ega bo’lasiz.

Reaktivlik

Svelte’ning reaktivlik modeli juda oddiy, lekin kuchli. Svelte’dagi reaktiv yozuvlar oddiy sintaksisda yoziladi va bu, masalan, elektron jadvallardagi formulalarni eslatadi. Quyida asosiy Svelte komponenti keltirilgan:

<script>
  let count = 0;
 
  function increment() {
    count += 1;
  }
</script>
 
<div>{count}</div>
<button on:click={increment}>
  Click me
</button>

Ushbu misolda {count} sintaksisi markup ichida count o’zgaruvchisi o’zgarganda avtomatik yangilanadi. Bu React’ning JSX’iga o’xshaydi, ammo bir asosiy farq bor: Svelte’da bu reaktivlik avtomatik tarzda amalga oshadi. DOM’ni yangilash uchun setter funksiyasini chaqirish yoki maxsus API’dan foydalanish shart emas; o’zgaruvchiga yangi qiymat tayinlashning o’zi kifoya va Svelte qolgan ishni o’zi bajardi.

Svelte, shuningdek, reaktiv yozuv sintaksisini ham taqdim etadi, bu orqali reaktiv ma’lumotlar asosida qiymatlarni hisoblash mumkin:

<script>
  let count = 0;
  let doubleCount = 0;
 
  $: doubleCount = count * 2;
 
  function increment() {
    count += 1;
  }
</script>
 
<div>{doubleCount}</div>
<button on:click={increment}>
  Click me
</button>

Bu misolda doubleCount avtomatik tarzda count o’zgarganida yangilanadi. Bu Vue’dagi computed properties (hisoblangan xususiyatlar)ni eslatadi, ammo biroz oddiyroq sintaksisda.

Svelte’ning kompilyatorga asoslangan yondashuvi bir qancha afzalliklarga ega. Bu odatda tezroq ish vaqti samaradorligini ta’minlaydi, chunki virtual DOM diffing va patching (farqni topish va tuzatish) jarayoniga ehtiyoj yo’q. Buning o’rniga, Svelte DOM’ni bevosita yangilaydigan kod yaratadi.

Shu bilan birga, bu yondashuv bilan bog’liq ijobiy va salbiy jihatlar ham mavjud. Svelte’ning kompilyatorga asoslangan tabiati virtual DOM’ga asoslangan freymvorklar taklif qiladigan ba’zi dinamik imkoniyatlarni, masalan, dinamik komponent turlarini ifodalashni biroz qiyinroq yoki batafsilroq qiladi. Shuningdek, Svelte ekotizimi React, Vue va Angular’nikiga qaraganda kichikroq va yoshroq bo’lgani uchun, unda resurslar, kutubxonalar va hamjamiyat yechimlari kamroq bo’lishi mumkin.

Runiklar (Runes)

Runiklar — bu Svelte kompilyatoriga ta’sir qiluvchi maxsus belgilar. Bugungi kunda Svelte let, =, export kalit so’zi va $: belgilaridan maxsus ma’nolar bilan foydalanadi, lekin runiklar funksiya sintaksisi orqali shunga o’xshash va qo’shimcha imkoniyatlarni ham taqdim etadi.

Misol uchun, reaktiv holatni e’lon qilish uchun $state runikidan foydalanish mumkin:

<script>
// let count = 0;
 let count =$state(0);
 
  function increment() {
    count += 1;
  }
</script>
 
<button on:click={increment}>
  clicks: {count}
</button>

Ilovalar murakkablashgani sayin, qaysi qiymatlar reaktiv ekanligini va qaysilari reaktiv emasligini aniqlash qiyin bo’lib qoladi. Hozirgi amaliyot faqat komponentning yuqori darajasida let bilan e’lon qilingan qiymatlar uchun ishlaydi, bu esa tushunmovchiliklarni keltirib chiqarishi mumkin. .svelte fayllarida bir xil, .js fayllarida esa boshqacha ishlash xatti-harakati, masalan, kodni ko’plab joylarda qayta yozish zarurati tug’ilganda uni refactor qilishni murakkablashtiradi.

Runiklar yordamida reaktivlik .svelte fayllarining chegarasidan tashqariga ham kengayadi. Masalan, hisoblagich logikasini bir nechta komponentlar o’rtasida qayta ishlatilishi mumkin bo’lgan tarzda inkapsulyatsiya qilishni xohlasangiz, bugungi kunda .js yoki .ts faylida maxsus saqlovchi (store) yaratishingiz kerak bo’ladi:

import { writable } from "svelte/store";
 
export function createCounter() {
  const { subscribe, update } = writable(0);
 
  return {
    subscribe,
    increment: () => update((n) => n + 1),
  };
}

Chunki bu saqlovchi shartnomasini (store contract) amalga oshiradi — ya’ni qaytarilgan qiymat subscribe metodiga ega — biz store qiymatini $ prefiksini qo’shish orqali olamiz:

<script>
import { createCounter } from './counter.js';
 
const counter = createCounter();
// let count = 0;
 
// function increment() {
//   count += 1;
// }
</script>
<!-- <button on:click={increment}> -->
<!-- clicks: {count} -->
<button on:click={counter.increment}>
  clicks: {$counter}
</button>

Bu ishlaydi, lekin biroz g’alati! Store API yanada murakkab narsalarni bajarishga uringanda, juda noqulay bo’lib qolishi mumkin. Runiklar yordamida, bu jarayon ancha osonlashadi:

// import { writable } from 'svelte/store';
 
export function createCounter() {
// const { subscribe, update } = writable(0);
   let count = $state(0);
 
  return {
 // subscribe,
 // increment: () => update((n) => n + 1)
    get count() { return count }
    increment: () => count += 1,
  };
}
<script>
    import { createCounter } from './counter.js';
 
    const counter = createCounter();
</script>
 
<button on:click={counter.increment}>
<!-- clicks: {$counter} -->
     clicks: {counter.count}
</button>

E’tibor bering, biz qaytarilgan obyekt ichida get xususiyatidan foydalanmoqdamiz, shuning uchun counter.count har doim hozirgi qiymatga ishora qiladi, funksiya chaqirilgan vaqtdagi qiymatga emas.

Ishlash vaqtida reaktivlik (Runtime reactivity)

Bugungi kunda Svelte kompilyatsiya vaqtida reaktivlik(compile-time reactivity)dan foydalanadi. Bu, agar sizda $: yorlig’idan foydalanadigan ba’zi kod bo’lsa va u avtomatik ravishda qayta ishlanishi kerak bo’lsa, bu qaramliklar Svelte sizning komponentingizni kompilyatsiya qilganda aniqlanadi:

<script>
export let width;
export let height;
 
// `width` yoki `height` o'zgarganda
// kompilyator `area`ni qayta hisoblash kerakligini biladi...
$: area = width * height;
 
// ...va u o'zgarganda
// `area`ning qiymatini log qilishini biladi
$: console.log(area);
</script>

Bu yaxshi ishlaydi…garchi bu ishlamasa. Faraz qilaylik, biz kodni quyidagicha refactor qilaylik:

// @errors: 7006 2304
const multiplyByHeight = (width) => width * height;
$: area = multiplyByHeight(width);

Chunki $: area = ... e’lon qilinishi faqat widthni ko’radi, bu height o’zgarganda qayta hisoblanmaydi. Natijada, kodni refactor qilish qiyinlashadi va Svelte qachon qanday qiymatlarni yangilashini tushunish ma’lum darajadagi murakkablikdan keyin juda qiyin bo’lib qolishi mumkin.

Svelte 5’da yangi runiklar

Svelte 5 $derived va $effect runiklarini taqdim etadi, bu esa o’z ifodalari qaramliklarini baholanganida aniqlaydi:

<script>
let { width, height } = $props(); // `export let` o'rniga
 
const area = $derived(width * height);
 
$effect(() => {
  console.log(area);
});
</script>

Yana, $state, $derived va $effect sizning .js va .ts fayllaringizda ham ishlatilishi mumkin.

Signalni kuchaytirish

Boshqa barcha freymvorklar singari, Svelte ham Knockout har doim haqligini anglab yetdi.

Svelte 5’ning reaktivligi signallar yordamida boshqariladi, bu asosan 2010 yilda Knockout tomonidan amalga oshirilgan narsalardir. So’nggi paytlarda, signallar Solid tomonidan ommalashgan (keyinchalik bu haqida ko’proq ma’lumot beramiz) va boshqa ko’plab freymvorklar tomonidan qabul qilingan. Svelte 5’da signallar to’g’ridan-to’g’ri o’zaro ta’sir qilinadigan narsalar emas, balki ichki ishlash mexanizmida amalga oshiriladigan tafsilot hisoblanadi.