Vue — istifadəçi interfeysləri yaratmaq üçün proqressiv JavaScript framework-üdür. Siz interfeysin mövcud verilənlərlə necə görünməli olduğunu təsvir edirsiniz, verilənlər dəyişəndə isə səhifəni Vue özü yeniləyir. Onu hazır sayta bir <script> teqi ilə qoşmaq və ya onun üzərində böyük birsəhifəli tətbiq (SPA) qurmaq olar.

Problem: DOM ilə əl ilə işləmək

Sayğac götürək: kliklərin sayı, beşinci klikdən sonra dəyişən ipucu və sayğac sıfır olduqca qeyri-aktiv qalan «Reset» düyməsi. Təmiz JavaScript-də:

html
<p>Clicks: <span id="count">0</span></p>
<p id="hint">Click the button</p>
<button id="inc">+1</button>
<button id="reset" disabled>Reset</button>

<script>
  let count = 0

  const countEl = document.querySelector('#count')
  const hintEl = document.querySelector('#hint')
  const resetBtn = document.querySelector('#reset')

  // verilənlərin hər dəyişikliyindən sonra bütün asılı yerləri əl ilə yeniləyirik
  function render() {
    countEl.textContent = count
    hintEl.textContent = count >= 5 ? 'Enough clicking!' : 'Click the button'
    resetBtn.disabled = count === 0
  }

  document.querySelector('#inc').addEventListener('click', () => {
    count++
    render()
  })

  resetBtn.addEventListener('click', () => {
    count = 0
    render()
  })
</script>

Kod işləyir, amma burada çoxlu köməkçi iş var: elementləri tapmaq, hadisə emalçılarını bağlamaq, hər dəyişiklikdən sonra render() çağırmaq və orada verilənlərdən asılı olan bütün yerləri yeniləmək. Bu, imperativ yanaşmadır: siz brauzerə səhifəni necə dəyişməyi əmr edirsiniz. Elementlər yüzlərlə olanda və verilənlər bir çox yerdən dəyişəndə onlardan birini yeniləməyi unutmaq asandır — və interfeys yanlış məlumat göstərəcək.

Deklarativ UI: həmin sayğac Vue ilə

Vue deklarativ yanaşma təklif edir: ekranda verilənlərdən asılı olaraq nə olmalı olduğunu bir dəfə təsvir edirsiniz, sinxronlaşdırmanı isə framework öz üzərinə götürür. Qısaca: UI = f(state).

html
<div id="app">
  <p>Clicks: {{ count }}</p>
  <p>{{ count >= 5 ? 'Enough clicking!' : 'Click the button' }}</p>
  <button @click="count++">+1</button>
  <button :disabled="count === 0" @click="count = 0">Reset</button>
</div>

<script type="module">
  import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

  createApp({
    setup() {
      const count = ref(0) // reaktiv dəyər: Vue onun dəyişikliklərini izləyir
      return { count }     // count-u şablonda əlçatan edirik
    }
  }).mount('#app')         // Vue <div id="app"> daxilini idarə edir
</script>

#app daxilindəki markup şablona çevrildi: {{ count }} dəyəri çıxarır, @click emalçı bağlayır, :disabled atributu ifadəyə bağlayır (ətraflı — şablonlar bölməsində). ref(0) reaktiv dəyər yaradır: count dəyişəndə Vue ondan asılı yerləri özü yeniləyir. Beş klikdən sonra DOM belə görünür:

html
<div id="app" data-v-app="">
  <p>Clicks: 5</p>
  <p>Enough clicking!</p>
  <button>+1</button>
  <button>Reset</button>
</div>

Düymə disabled atributunu itirdi, ipucu dəyişdi — bunun üçün ayrıca kod yazmadan (data-v-app — tətbiq konteynerinin nişanıdır).

💡 Nümunəni index.html faylında saxlayıb brauzerdə açın — quraşdırma lazım deyil. Onlayn sınaq meydançası: Vue Playground.

«Proqressiv» framework

«Proqressiv» o deməkdir ki, Vue layihəyə tədricən, ehtiyac olan həcmdə əlavə olunur:

SəviyyəNecə qoşulurNə vaxt uyğundur
Səhifədə vidcetCDN-dən <script type="module">hazır saytda kalkulyator və ya filtr (Laravel, WordPress)
SPAVite layihəsi, .vue fayllarışəxsi kabinet, admin panel
SPA + ekosistem+ Vue Router, Piniaçoxlu səhifə və ümumi vəziyyət
NuxtVue üzərində meta-frameworkSEO, server tərəfində render

Birinci səviyyə: Vue serverin yaratdığı adi səhifədə yalnız bir bloku «canlandırır».

html
<main>
  <h1>Delivery</h1>
  <!-- səhifənin adi HTML-i: Vue ona toxunmur -->
  <p>Free delivery for orders over 50 AZN.</p>

  <div id="delivery-calc">
    <label>Weight: <input v-model.number="weight" type="number" min="0"> kg</label>
    <p>Price: {{ price }} AZN</p>
  </div>
</main>

<script type="importmap">
  { "imports": { "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.prod.js" } }
</script>

<script type="module">
  import { createApp, ref, computed } from 'vue'

  createApp({
    setup() {
      const weight = ref(1)
      const price = computed(() => 5 + weight.value * 2) // 5 AZN + hər kq üçün 2 AZN
      return { weight, price }
    }
  }).mount('#delivery-calc')
</script>

Vue yalnız #delivery-calc blokunu idarə edir: çəkini 3 yazın — qiymət dərhal 11 AZN olacaq. Import map tam URL əvəzinə from 'vue' yazmağa imkan verir, .prod.js isə production build-dir. v-model və computed-i sonra öyrənəcəyik.

SPA-da kod tək fayllı komponentlərə köçür — şablon, məntiq və stillərin bir yerdə olduğu .vue fayllarına:

vue
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <p>Clicks: {{ count }}</p>
  <button @click="count++">+1</button>
  <button :disabled="count === 0" @click="count = 0">Reset</button>
</template>

Şablon eynidir, <script setup> isə createApp və return-dən azad edir: skriptdə elan olunan hər şey şablonda əlçatandır. .vue fayllarını Vite kompilyasiya edir — bütün kurs boyu belə yazacağıq.

Vue digər framework-lər arasında

Dörd həllin hamısı deklarativ UI-ı komponentlərdən qurur, amma fərqli fəlsəfə ilə:

VueReactAngularSvelte
Nədirproqressiv frameworkUI kitabxanası«hər şey daxil» platformakompilyator-framework
MarkupHTML şablonları (istəyə görə JSX)JSXHTML şablonlarıHTML şablonları
ReaktivlikProxy əsasında ref/reactiveuseState, komponentin yenidən render-iSignalsrunes: $state
Marşrutlaşdırma və vəziyyətrəsmi Vue Router və Piniakənar kitabxanalardaxildirSvelteKit
Meta-frameworkNuxtNext.jsAngular SSRSvelteKit

Vue-nun güclü tərəfləri — tanış HTML üzərində şablonlar, nöqtəvi reaktivlik, əla sənədləşmə və rəsmi alətlər. O, Laravel ekosistemində populyardır, GitLab interfeysi onunla yazılıb. Biliklər köçürülə biləndir: komponentlər və reaktivlik dörd framework-ün hamısında oxşar qurulub.

Ekosistem və aktual versiya

AlətNə üçünKursda harada
Vitedev-server və buildnövbəti mövzu
Vue RouterSPA-da səhifələr və naviqasiya«Marşrutlaşdırma» bölməsi
Piniaümumi vəziyyət anbarı«Pinia» bölməsi
VueUseyüzlərlə hazır composable«Composables» bölməsi
NuxtSSR, SEO, fayl əsaslı marşrutlarson bölmə

Aktual budaq — Vue 3.5-dir (yazıldığı vaxt 3.5.43); Vapor Mode render rejimi ilə 3.6 versiyası Release Candidate statusundadır. Vue 2 31 dekabr 2023-cü ildən dəstəklənmir, amma internetdə onun üçün nümunələr hələ çoxdur.

Tipik səhvlər

Vue tətbiqi daxilində DOM-u əl ilə dəyişmək. document.querySelector('#count').textContent = 10 yalnız növbəti yenilənməyə qədər işləyəcək — Vue elementi öz verilənlərinə görə yenidən çəkəcək. DOM-u yox, verilənləri dəyişin (count.value = 10).

type="module"-u unutmaq. Adi skript import-u başa düşmür və brauzer Uncaught SyntaxError: Cannot use import statement outside a module xətası verəcək.

html
<script>import { createApp } from 'vue'</script>               <!-- ❌ -->
<script type="module">import { createApp } from 'vue'</script> <!-- ✅ -->

Vue 2 nümunələrini köçürmək. new Vue({ el, data }), Vue.component(), {{ price | currency }} filtrləri və $on Vue 3-də işləmir. Nümunələrdə createApp axtarın.

İşlək saytda dev build-i saxlamaq. vue.esm-browser.js daha ağırdır və konsola «You are running a development build of Vue» yazır. Production üçün vue.esm-browser.prod.js, tam tətbiq üçün isə Vite layihəsi lazımdır.

Xülasə

  • Vue deklarativ UI üçün framework-dür: siz nəticəni verilənlərə görə təsvir edirsiniz, DOM-u isə Vue yeniləyir.
  • ref() reaktiv dəyər yaradır, {{ }}, @click və :disabled olan şablon markup-ı təsvir edir, createApp().mount() tətbiqi işə salır.
  • «Proqressiv» — tədricən tətbiq olunan deməkdir: CDN vasitəsilə vidcetdən Vite üzərində SPA-ya və Nuxt-a qədər.
  • Vue-da HTML şablonları, nöqtəvi reaktivlik və rəsmi ekosistem var: Vite, Vue Router, Pinia, VueUse, Nuxt.
  • Aktual versiya — Vue 3.5; new Vue() olan kod köhnəlmiş Vue 2-yə aiddir.

Praktika

  1. Vue Playground-u açın, nümunədə ekrana çıxan dəyəri dəyişin və sağdakı nəticənin necə yeniləndiyinə baxın.
  2. Vue sayğacını index.html faylında saxlayın və brauzerdə açın. Sıfırda qeyri-aktiv olan «-1» düyməsi əlavə edin.
  3. Sayğacın hər iki versiyasına (JS və Vue) «Even»/«Odd» sətri əlavə edin — kliklərin sayı cüt, yoxsa təkdir. Hər birində neçə sətri dəyişməli olduğunuzu müqayisə edin.
  4. Kafe səhifəsi üçün «Bəxşiş kalkulyatoru» vidceti hazırlayın: məbləğ sahəsi, faiz sahəsi və «Tip: … AZN, Total: … AZN» sətri. Vue yalnız #tip-calc blokunu idarə edir.

💡 4-cü tapşırıqda çatdırılma nümunəsindəki kimi import map və computed, həmçinin v-model.number istifadə edin, əks halda sahələrdən dəyərlər sətir kimi gələcək.