Vue.js Composition API: modernūs komponentai

Kodėl Composition API atsirado ir kas jį daro tokį ypatingą

Kai 2020 metais Vue 3 išvydo dienos šviesą, kartu su juo atėjo ir Composition API – naujas būdas kurti komponentus, kuris iš pradžių sukėlė nemažai diskusijų bendruomenėje. Vieni programuotojai džiūgavo, kiti skeptiškai žiūrėjo į dar vieną būdą daryti tą patį. Tačiau praėjus keliems metams, Composition API tapo ne tik priimtas, bet ir labai mėgstamas daugelio Vue kūrėjų.

Tradicinis Options API puikiai tarnavo Vue bendruomenei daugelį metų. Jis buvo intuityvus, lengvai suprantamas ir puikiai tiko mažesniems projektams. Bet kai komponentai augo, kai logika tapo sudėtingesnė, o kodą reikėjo pakartotinai naudoti skirtinguose komponentuose, Options API ribotumas tapo vis akivaizdesnis.

Composition API gimė kaip atsakas į šiuos iššūkius. Jis leidžia organizuoti kodą pagal logiką, o ne pagal opcijų tipus. Vietoj to, kad skaidytumėte kodą į data, methods, computed ir watch sekcijas, galite grupuoti susijusią logiką kartu. Tai ypač naudinga didesniuose komponentuose, kur viena funkcionalumo dalis gali apimti kelis metodus, reaktyvius kintamuosius ir computed properties.

Pirmieji žingsniai su setup funkcija

Viskas prasideda nuo setup() funkcijos – tai Composition API širdis. Ši funkcija vykdoma prieš komponentui sukuriant, dar prieš created lifecycle hook’ą. Čia apibrėžiate visą komponentų logiką, reaktyvius duomenis ir funkcijas, kurias norite naudoti template’e.

Štai paprastas pavyzdys, kaip tai atrodo praktikoje:




Pastebėjote <script setup>? Tai sintaksinis cukrus, kuris dar labiau supaprastina Composition API naudojimą. Nereikia grąžinti kintamųjų iš setup funkcijos – viskas, kas apibrėžta <script setup> bloke, automatiškai tampa prieinamu template’e. Tai gerokai sumažina boilerplate kodą ir daro viską skaitomesnį.

Svarbu suprasti, kad ref() sukuria reaktyvią nuorodą į reikšmę. Todėl JavaScript kode turite naudoti .value, kad pasiektumėte ar pakeistumėte reikšmę. Template’e Vue automatiškai išpakuoja šias nuorodas, todėl galite tiesiog rašyti {{ count }} vietoj {{ count.value }}.

Reaktyvumas: ref vs reactive

Vienas iš dažniausių klausimų, su kuriais susiduria naujokai Composition API pasaulyje: kada naudoti ref(), o kada reactive()? Abi funkcijos sukuria reaktyvius duomenis, bet skirtingais būdais.

ref() puikiai tinka primityvėms – skaičiams, eilutėms, boolean reikšmėms. Jis taip pat veikia su objektais ir masyvais, bet tada turite naudoti .value prieigą. Daugelis kūrėjų renkasi ref() visur dėl nuoseklumo – visada žinai, kad reikia naudoti .value.

reactive(), kita vertus, skirtas objektams ir masyvams. Jis sukuria reaktyvų proxy objektą, ir jums nereikia .value:

import { reactive } from 'vue'

const state = reactive({
  user: {
    name: 'Jonas',
    age: 25
  },
  isLoggedIn: false
})

// Prieiga be .value
console.log(state.user.name)
state.isLoggedIn = true

Tačiau reactive() turi vieną svarbų apribojimą – negalite pakeisti viso objekto. Jei parašysite state = { ...naujiDuomenys }, prarasite reaktyvumą. Su ref() tokių problemų nėra, nes galite tiesiog pakeisti .value.

Mano asmeninis patarimas po kelių metų darbo su Vue 3: pradedantiesiems geriau laikytis ref() visur. Taip išvengsite subtilių klaidų ir kodas bus nuoseklesnis. Kai įgysite daugiau patirties, galėsite eksperimentuoti su reactive() ten, kur tai logiškai tinka.

Composables – kodas, kurį galite nešiotis kišenėje

Čia Composition API tikrai spindi. Composables yra pakartotinai naudojamos funkcijos, kurios inkapsiliuoja reaktyvią logiką. Galvokite apie juos kaip apie mažus logikos blokus, kuriuos galite naudoti bet kuriame komponente.

Tarkime, kuriate aplikaciją, kur keliuose komponentuose reikia sekti pelės poziciją. Options API pasaulyje turėtumėte kopijuoti kodą arba naudoti mixins (kurie turi savo problemų). Su Composition API sukuriate composable:

// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)

  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  onMounted(() => {
    window.addEventListener('mousemove', update)
  })

  onUnmounted(() => {
    window.removeEventListener('mousemove', update)
  })

  return { x, y }
}

Dabar bet kuriame komponente galite tiesiog:




Gražu, ar ne? Logika aiškiai atskirta, lengvai testuojama ir pakartotinai naudojama. Composables tapo standartiniu būdu dalintis logika tarp komponentų Vue 3 ekosistemoje.

Kai kuriate savo composables, laikykitės kelių paprastų taisyklių: pradėkite pavadinimą su „use”, grąžinkite objektą su reaktyviomis reikšmėmis ir funkcijomis, ir tvarkykite cleanup’ą onUnmounted hook’e, jei reikia.

Lifecycle hooks naujame kontekste

Lifecycle hooks Composition API pasaulyje veikia šiek tiek kitaip nei Options API. Vietoj to, kad apibrėžtumėte juos kaip komponentų opcijas, importuojate ir kviečiate juos setup() funkcijoje.

Štai kaip atitinka senasis ir naujasis būdas:

  • beforeCreate ir created – nereikalingi, nes setup() vykdomas tuo pačiu metu
  • beforeMountonBeforeMount()
  • mountedonMounted()
  • beforeUpdateonBeforeUpdate()
  • updatedonUpdated()
  • beforeUnmountonBeforeUnmount()
  • unmountedonUnmounted()

Praktikoje tai atrodo taip:


Vienas iš didžiausių privalumų – galite kviesti tą patį hook kelis kartus. Tai ypač naudinga, kai naudojate kelis composables, ir kiekvienas iš jų turi savo onMounted logiką. Visi jie bus vykdomi tinkama tvarka.

Computed properties ir watchers moderniu būdu

Computed properties Composition API pasaulyje sukuriami naudojant computed() funkciją. Jie veikia panašiai kaip Options API, bet sintaksė šiek tiek skiriasi:

import { ref, computed } from 'vue'

const firstName = ref('Jonas')
const lastName = ref('Jonaitis')

const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`
})

// Arba su getter ir setter
const fullNameEditable = computed({
  get() {
    return `${firstName.value} ${lastName.value}`
  },
  set(newValue) {
    const names = newValue.split(' ')
    firstName.value = names[0]
    lastName.value = names[1]
  }
})

Watchers taip pat turi naują sintaksę. Yra keletas būdų stebėti pokyčius:

import { ref, watch, watchEffect } from 'vue'

const count = ref(0)
const message = ref('Labas')

// Stebėti vieną šaltinį
watch(count, (newValue, oldValue) => {
  console.log(`Count pasikeitė nuo ${oldValue} į ${newValue}`)
})

// Stebėti kelis šaltinius
watch([count, message], ([newCount, newMessage], [oldCount, oldMessage]) => {
  console.log('Kažkas pasikeitė!')
})

// watchEffect - automatiškai stebi visas naudojamas reaktyvias reikšmes
watchEffect(() => {
  console.log(`Count yra ${count.value}, message: ${message.value}`)
})

watchEffect() yra ypač patogus, kai norite automatiškai reaguoti į bet kokius reaktyvių duomenų pokyčius funkcijoje. Nereikia aiškiai nurodyti, ką stebite – Vue automatiškai tai apskaičiuoja.

Vienas svarbus skirtumas: watch() pagal nutylėjimą yra „lazy” – callback’as nebus iškviečiamas iš karto. Jei norite immediate vykdymo, pridėkite { immediate: true } opciją. watchEffect(), priešingai, vykdomas iš karto.

TypeScript integracija – kodėl tai svarbu

Vienas iš didžiausių Composition API privalumų yra puikus TypeScript palaikymas. Vue 3 buvo perrašytas TypeScript, ir Composition API buvo sukurtas su TypeScript galvoje nuo pat pradžių.

Options API su TypeScript visada buvo šiek tiek nepatogus. this kontekstas, sudėtingas tipų išvedimas, papildomi dekoratoriai – visa tai sukūrė trinties. Composition API šias problemas išsprendžia elegantiškai:


Tipai išvedami automatiškai daugeliu atvejų. Pavyzdžiui, jei parašote const count = ref(0), TypeScript automatiškai supranta, kad tai Ref<number>. Computed properties taip pat automatiškai išveda tipus pagal return reikšmę.

Composables su TypeScript tampa dar galingesni. Galite apibrėžti aiškias sąsajas tam, ką grąžina jūsų composable, ir gauti pilną IDE palaikymą:

// composables/useApi.ts
import { ref, Ref } from 'vue'

interface UseApiReturn {
  data: Ref
  loading: Ref
  error: Ref
  fetch: () => Promise
}

export function useApi(url: string): UseApiReturn {
  const data = ref(null)
  const loading = ref(false)
  const error = ref(null)

  async function fetch() {
    loading.value = true
    error.value = null
    
    try {
      const response = await fetch(url)
      data.value = await response.json()
    } catch (e) {
      error.value = e as Error
    } finally {
      loading.value = false
    }
  }

  return { data, loading, error, fetch }
}

Jei dar nenaudojate TypeScript su Vue 3, rimtai apsvarstykite tokią galimybę. Pradinis mokymosi kreivė gali atrodyti statesni, bet ilgalaikiai privalumai – geresnė kodo kokybė, mažiau klaidų, puikus IDE palaikymas – tikrai to verti.

Kaip visa tai sujungti į darbo procesą

Perėjimas prie Composition API nebūtinai reiškia, kad turite perrašyti visą esamą kodą. Vue 3 puikiai palaiko abu API stilius tame pačiame projekte. Galite pradėti naudoti Composition API naujuose komponentuose, o senus palikti su Options API.

Tačiau jei planuojate migruoti, štai keletas praktinių patarimų iš asmeninės patirties:

Pradėkite nuo mažų, nepriklausomų komponentų. Utility komponentai, mažos formos, paprastos kortelės – tai puikios vietos pradėti. Išmoksite sintaksę be didelio streso.

Identifikuokite pakartotinai naudojamą logiką ir iškelkite ją į composables. Tai viena iš didžiausių Composition API vertybių. Jei matote, kad ta pati logika kartojasi keliuose komponentuose, tai idealus kandidatas composable’ui.

Neskubėkite su sudėtingais komponentais. Dideli, sudėtingi komponentai su daug būsenų ir logikos gali būti sudėtingi migruoti. Geriau pirmiausia išmokite pagrindus su paprastesniais atvejais.

Naudokite <script setup> sintaksę. Ji gerokai sumažina boilerplate kodą ir daro komponentus skaitomesnius. Nebent turite labai specifinį atvejį, visada rinkitės <script setup>.

Organizuokite logiką logiškai. Vienas iš didžiausių Composition API privalumų – galite grupuoti susijusią logiką kartu. Naudokite komentarus, kad atskirtumėte skirtingas logines sekcijas:


Testuokite anksti ir dažnai. Composition API komponentai paprastai lengviau testuojami nei Options API, nes logika labiau atskira. Composables ypač lengva testuoti izoliuotai.

Ir paskutinis, bet ne mažiau svarbus patarimas – skaitykite kitų žmonių kodą. Vue 3 ekosistemoje dabar yra tūkstančiai open-source projektų, naudojančių Composition API. Pažiūrėkite, kaip kiti organizuoja savo kodą, kaip kuria composables, kokias patterns naudoja. GitHub ir CodeSandbox yra neįkainojami mokymosi šaltiniai.

Composition API gali atrodyti kaip didelis pokytis, ypač jei esate įpratę prie Options API. Bet kai įsisavinate pagrindus ir pradėdate matyti privalumus – geresnę kodo organizaciją, lengvesnį pakartotinį naudojimą, puikų TypeScript palaikymą – grįžti atgal nebenorėsite. Tai tikrai modernesnė, lankstesnė ir galingesnė priemonė kurti Vue komponentus, ir ji puikiai atspindi, kur eina visa frontend kūrimo industrija.

Daugiau

Istio service mesh Kubernetes klasteriuose