Frontend

Trzy rzeczy, za które możesz pokochać Vue 3

vue divante

Nowa wersja Vue wprowadziła wiele interesujących funkcji i zmian. Nie tylko poprawiły one ogólną wydajność, ale przede wszystkim, jeszcze bardziej ułatwiły programowanie w tej technologii. Chciałabym Wam pokazać te trzy rzeczy, za które ja pokochałam Vue 3. Zaprezentuję je na prostym przykładzie dodawania produktu do koszyka.

W branży e-commerce jest to kluczowa funkcjonalność. Mam nadzieję, że uda mi się tym sposobem Was przekonać do zagłębienia się również w inne możliwości jakie daje nam najnowsza wersja frameworku.

Marta Radziszewska. Frontend Developer w Divante. Wcześniej architekt krajobrazu, dzisiaj pracuje nad rozwojem multibrandowej aplikacji e-commerce. Zakochana w połączeniu Vue.js + Typescript. W swojej pracy bardzo dużo uwagi poświęca reużywalności komponentów, prostym rozwiązaniom jak również accessibility. Pasjonuje ją User Experience Design. Wyznaje zasadę, że roślin w domu nigdy za wiele!


1. Composition API === „Reużywalność”

Jak już za pewnie większość z Was wie, jest to całkowicie nowe podejście do sposobu budowania komponentów. Pozwala zorganizować kod w sposób bardziej logiczny i „reużywalny” – to naprawdę jedno z najlepszych dóbr nowej wersji Vue, posiadające również wsteczną kompatybilność!

Zobaczcie na prosty przykład listy produktów, który używa nowego sposobu Composition API. To z tego miejsca będziemy używać naszej metody dodawania do koszyka.

<template>
	<div> You have {{ cartItemsCounter }} product/products in cart.</div>
  <div v-for="product in products" :key="product.id">
    <h2>{{ product.name }}</h2>
    <button @click="addToCart(product)">
       Add To Cart 
    </button>
  </div>
</template>

<script>
import { ref, computed } from "vue";

export default {
  props: {
    products: {
      type: Array,
      default: () => [],
    },
  },
  setup(props, context) {
    const itemsInCart = ref([]);
    const cartItemsCounter = computed(() => itemsInCart.value.length);
    const addToCart = (product) => {
      itemsInCart.value.push(product);
    };
    return {
      cartItemsCounter,
      addToCart,
    };
  },
};
</script>

Co się zmieniło?

Na początku mojej przygody z programowaniem zawsze słyszałam: „rozbij to na części pierwsze i wszystko stanie się proste”. Spróbujmy więc wyodrębnić najważniejsze zmiany z powyższego kodu, krótko je omawiając.

  • Importowanie poprzez Tree Shaking
import { ref, computed } from "vue";

Importowanie przez wyciągnięcie tylko tych funkcji, które aktualnie są przez nas wykorzystywane w danym komponencie – tzw. „tree-shaking” – co oznacza, że jeśli nie użyjesz danej funkcji, nie będzie ona zawarta w produkcyjnej paczce.

  • Metoda setup()
setup(props, context) {
	...
  return {
   ...
  }
}

Zamiast dotychczasowej organizacji kodu poprzez Options API, gdzie to opcje dyktowały nam ułożenie logiki (data, computed, lifecycle hooks) mamy jedną metodę – setup(), w której odbywa się cała magia – wszystko, co zwrócimy w tej metodzie – właściwości, funkcje – będzie dostępne w naszym szablonie.

Warto zapamiętać, że:

– setup wywołuje się zaraz po beforeCreate() i tuż przed created(),

– setup daje nam dostęp do dwóch parametrów: naszych zdefiniowanych „propsów” oraz contextu – czyli atrybutów, slotów i emitów, które możemy zdestrukturyzować nie martwiąc się o ich reaktywność – setup(props, { attrs, slots, emit }).

  • Elementy API wspierające reaktywność
const itemsInCart = ref([]);

W tym miejscu deklarujemy reaktywną właściwość poprzez zapisanie do metody ref() – używamy jej do zmiennych prostych lub Object jeśli chcemy, aby jego wartości nie były reaktywne. Zwracana wartość to reaktywna referencja, która jest obiektem a jej wartość jest przechowywana w kluczu „value” – dlatego dostęp do naszej wartości mamy zawsze poprzez odniesienie do itemsInCart.value.

W naszym przypadku jest to początkowo pusta tablica, którą będziemy wypełniać produktami dodanymi do koszyka a potem poprzez właściwość „computed” będziemy zwracać aktualną ilość produktów jakie mamy w koszyku.

const cartItemsCounter = computed(() => itemsInCart.value.length);
const addToCart = (product) => {
  itemsInCart.value.push(product);
};

Na końcu zwracamy tylko to, co jest nam potrzebne do wykonania akcji lub wyświetlenia docelowych wartości:

return {
  cartItemsCounter,
  addToCart,
};

Gotowe! Tym sposobem wykorzystaliśmy nowe Composition API do zbudowania naszego komponentu. Ale to nie jest wszystko, co możemy osiągnąć. Zauważcie, że komponent nasz zawiera logikę, która na pewno będzie współdzielona między innymi komponentami:

  • wyświetlenie aktualnej ilości produktów w koszyku,
  • metoda addToCart,
  • w rzeczywistości jeszcze odwoływanie się do backendu.

Na pewno znacie inne sposoby na wyodrębnienie logiki, aby była współdzielona (mixiny, scopedSlots). Jak to osiągnąć wykorzystując nowe możliwości Vue 3?

useComposable(), please!

Dobrą praktyką dla programisty jest utrzymywanie kodu jak najbardziej „reużywalnego„, zwłaszcza w dużych aplikacjach o wielu strukturach. Niestety słowo nie istnieje w języku polskim natomiast oddaje całokształt idei, która powinna zdominować myślenie programistów – dlatego tak często tu się pojawia.

Dzięki Composition API jesteśmy w stanie bez problemu to uzyskać. Spróbujmy na podstawie powyższego kodu wydzielić metody tworząc tzw. composable, czyli funkcje kompozycyjne uzyskując tym samym reużywalne metody, które można wykorzystać w innych komponentach, co również pozwoli nam przechowywać wspólny stan w jednym miejscu.

Nasza logika dotyczy dodawania produktów do koszyka oraz wyświetlanie aktualnej ilości – można zatem wydzielić logikę do jednego pliku:

/composables/useCart.js

import { computed, reactive } from "vue";

// Współdzielony state
const itemsInCart = ref([]);

export function useCart () {
  const cartItemsCounter = computed(() => itemsInCart.products.length);

  const addToCart = (product) => {
    itemsInCart.products.push(product);
  };

  return {
    addToCart,
    cartItemsCounter
  };
};

Teraz zobaczcie, jak metoda setup wygląda w naszym komponencie:

  setup(props, context) {
		const { cartItemsCounter, addToCart } = useCart();
    return {
      cartItemsCounter,
      addToCart,
    };
  },

Zyskujemy naprawdę wiele:

  • zorganizowany kod === czysty kod,
  • reużywalną logikę pomiędzy komponentami,
  • współdzielenie stanu, dzięki czemu możemy zawsze odpytać o aktualną wartość.

Wyobraźcie sobie teraz pracę w rozbudowanej aplikacji, gdzie macie tak poukładane metody – bajka.

Cały przykładowy kod znajdziecie tutaj.

2. Typescript

Bez żadnych wątpliwości można stwierdzić, że Typescript ułatwia życie. To nie jest żadna nowość, ponieważ Vue 2 miało już wsparcie tej technologii, natomiast nowa wersja Vue została całkowicie od zera przepisana bazując właśnie na nim. Teraz można bez obaw korzystać z dobroci Typescripta i cieszyć się pięknie otypowanym JavaScript’em.

Jak się nie bać z niego korzystać?

Spróbujmy na podstawie naszego komponentu, przejść przez niektóre

  • definiowane komponentów
<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  ...
})
</script>
  • typowanie propsów
import { PropType } from 'vue'

interface Product {
  title: string
  id: number
}

 props: {
    product: {
      type: Object as PropType<Product>,
    },
  },
  • typowanie reaktywnych elementów
const year = ref<string | number>('2020')
const itemsInCart = ref<Product[]>([])
  • budowanie interfejsów dla dużych obiektów
interface Product {
  title: string
  id: number
}

const addToCart = (product: Product) => {
    itemsInCart.products.push(product);
};

const product = reactive<Product>({ title: 'Super product title', id: 123 })

Co jeszcze można uzyskać korzystając z tego języka?

  • Podpowiadanie!

IDE obecnie pozwala podpowiedzieć, jaki parametr przyjmuje metoda, natomiast Typescript jednocześnie sprawdzi i dopilnuje, że Twój parametr jest odpowiedniego typu, nie pozwalając na nic innego. Koniecznie sprawdźcie oficjalną dokumentację: https://www.typescriptlang.org/docs/.

3. Multiple v-model

Dyrektywa v-model została ujednolicona i pozwala nam na więcej możliwości – mowa właśnie o wielokrotnym jej użyciu. Zmiany dotyczą również samego zapisu, które przy migracji mogą stanowić utrudnienie. Nie będziecie tego jednak żałować, ponieważ dzięki takiej zmianie możemy skorzystać z bardzo przyjemnego zapisu powiązania v-model na jednym niestandardowym komponencie zawierającym np. cały formularz.

<UserForm v-model:name="user.name" v-model:lastName="user.lastName" />

Zapis jest banalnie prosty i przede wszystkim czytelny.

A to co się zmieniło i powinniście zapamiętać przy migracji do Vue 3:

valuemodelValue

@input@update:modelValue

Zobaczcie na prosty przykład użycia v-model.

Podsumowanie

Tylko trzy rzeczy? Nie, jest ich więcej! Oprócz głównych zmian jak Composition API jest wiele mniejszych udoskonaleń, które sprawiają, że Vue staje się coraz częściej wybieraną technologią w tworzeniu nie tylko małych, ale i bardzo rozbudowanych aplikacji.

Bardzo Was zachęcam do poczytania oficjalnej dokumentacji Vue 3, która jest przygotowana doskonale przez ich zespół → https://v3.vuejs.org/.

Na dodatek, Evan You przygotował aplikację pozwalającą na testowanie kodu napisanego w Vue 3 oraz TS i sprawdzenie w kompilatorze jak wygląda nasz kod wynikowy! → http://sfc.vuejs.org/.

Dla tych co dotrwali do końca, mam jeszcze jedną rzecz, z którą chciałabym się podzielić. Zauważyliście, że w naszym kodzie wewnątrz <template> nie dodajemy już elementu, który opakowuje wszystkie pojedyncze elementy? To bardzo mała poprawa, ledwo zauważalna, ale cieszy oko. → zobaczcie więcej pod tym linkiem.


Zdjęcie główne artykułu pochodzi z unsplash.com.

Podobne artykuły

[wpdevart_facebook_comment curent_url="https://justjoin.it/blog/trzy-rzeczy-za-ktore-mozesz-pokochac-vue-3" order_type="social" width="100%" count_of_comments="8" ]