FRAMEWORK
Paweł Klockiewicz
Prawa do korzystania z materiałów posiada Software Development Academy
Edytor programistyczny
Visual Studio Code
Przeglądarka oparta o Chromium
Node.js umożliwia pisanie aplikacji w JavaScript po stronie backendowej (serwerowej). Jest oparty na środowisku wykonawczym V8 i napisany w C++. Pierwotnie miało być środowiskiem serwerowym dla aplikacji, ale programiści zaczęli go używać do tworzenia narzędzi wspomagających automatyzację zadań lokalnych. Od tego czasu ewoluował zupełnie nowy ekosystem narzędzi opartych na Node.js, aby zmienić oblicze front-endu.
npm (ang. Node Package Manager) jest menedżerem pakietów dla Node.js z setkami tysięcy pakietów.
Głównym celem jest automatyzacja zarządzania zależnościami i pakietami. Oznacza to, że można określić wszystkie zależności projektu w pliku package.json, a następnie za każdym razem, gdy trzeba będzie rozpocząć pracę z projektem, można wykonać polecenie npm install i natychmiast zainstalować wszystkie zależności.
node -v
npm -v
Problem z wyświetlaniem? Kliknij tutaj, aby otworzyć cheatsheet w nowym oknie.
Framework można zdefiniować jako narzędzie, które umożliwia tworzenie oprogramowania i systemów.
Framework jest abstrakcją, która zapewnia ogólną funkcjonalność i może być zmieniana przez dodatkowy kod napisany przez użytkownika, dostarczając w ten sposób kod specyficzny dla budowanej aplikacji.
Tworzenie oprogramowania to złożony proces, który wymaga wielu zadań. Korzystanie z frameworka pozwala skupić się na funkcjonalności na wysokim poziomie. Dzieje się tak, ponieważ każda funkcjonalność niskiego poziomu jest obsługiwana przez framework.
Vue jest otwartoźródłowym frameworkiem MVVM dla JavaScriptu do budowania aplikacji internetowych.
Pozwala na dodawanie interaktywnych zachowań i możliwości funkcjonalnych w dowolnym kontekście, w jakim jest wykonywany kod JavaScript.
Można go używać na pojedynczych stronach WWW do prostych zadań, jak również może stanowić podstawę całych aplikacji korporacyjnych.
WIDOK
MECHANIZM
WIĄZANIA
DANYCH
MODEL
WIDOKU
MODEL
Widok odpowiada za to, co widzi użytkownik, jednak wszelka logika związane z podejmowaniem decyzji zastała przeniesiona do modelu widoku. W tym przypadku widoki wyświetlają treści na podstawie dostępności oraz ilości danych w bieżącym stanie aplikacji.
Model widoku przechowuje reprezentacje danych aplikacji, zapisaną w obiekcie, który zazwyczaj jest nazywany magazynem. Magazyn zawiera wszystkie dane wymagane przez aplikację w dowolnym momencie jej dzielenia i określane wspólnie jako stan aplikacji.
Model jest trwałym repozytorium danych aplikacji. W niektórych architekturach aplikacji JavaScript model dziale wyłącznie jako magazyn i jest pozbawiony jakichkolwiek logicznych ograniczeń narzucanych na przychodzące dana, a tym samym przenosi wszelkie decyzje związane logiką biznesową na model widoku.
Mechanizm wiązania danych udostępnia dane widokowi w formie właściwości. Widoki używają tych danych, wywołując metody, które także są udostępniane przez mechanizm wiązania danych; metody te z kolei oporują na danych przechowywanych w magazynie w modelu widoku.
Model widoku, podobnie jak kontroler w MVC, jest odpowiedzialny za przekazywanie danych do modelu w celu ich utrwalenia. Jednak transakcje te nie muszą być realizowane synchronicznie, co pozwała użytkownikom na kontynuowanie korzystania z aplikacji.
WIDOK
MECHANIZM
WIĄZANIA
DANYCH
MODEL
Widoki można pisać w HTML i CSS.
HTML + CSS
JavaScript
Instancja Vue
Każda z aplikacji korzystających z tego frameworka musi mieć przynajmniej jedną instancję Vue.
Do opisania danych reprezentowanych przez model widoku oraz metod udostępnianych przez mechanizm wiązania danych domyślnie używa się języka JavaScript.
Istnieją dwa sposoby instalacji Vue – poprzez Node lub przez zalinkowanie pliku *.JS do HTML.
Najprostszą formą instalacji jest ta ostatnia, czyli bezpośrednie wstrzyknięcie Vue do statycznego pliku HTML.
Wystarczy po prostu utworzyć podstawowy plik HTML i dodać link do Vue CDN w <head>, a następnie utworzyć <div> z ID aplikacji.
// HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue App</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
1. Skopiuj kod z poprzedniego slajdu i utwórz nowy plik HTML.
2. Zawartość tagu <body> zastąp przez:
<div id="app">{{message}}</div>
<script>
const App = new Vue({
el: '#app',
data: {
message: 'Witaj, Świecie!',
},
})
</script>
3. Uruchom plik w przeglądarce.
Częściej zdarza się jednak korzystanie z ekosystemu Node w świecie front-endu. Najprostszym sposobem, w jaki można zainstalować Vue w tym ekosystemie, to instalacja dodatkowego narzędzia – Vue CLI.
// Node
Vue CLI (ang. Console Line Interface) to interfejs wiersza poleceń dla Vue. Narzędzie to pomaga szybko rozpocząć tworzenie aplikacji Vue.
CLI ułatwia pisanie złożonych aplikacji Vue.js bez konieczności zawracania sobie głowy budowaniem oraz transpilacją kodu.
# INSTALACJA
npm install -g @vue/cli
# NOWY PROJEKT
vue create my-project
1. Zainstaluj Vue CLI (patrz poprzedni slajd).
2. Utwórz nowy projekt Vue:
vue create vue-app
# Wybierz domyślne opcje
3. Przejdź do katalogu aplikacji i ją uruchom:
cd vue-app
npm run serve
Dla edytora Visual Studio Code warto jest zainstalować wtyczkę Vetur, która koloruje i formatuje składnię kodu Vue, a także oferuje inteligencje podpowiedzi.
Przydatną wtyczką podczas pracy z Vue jest również Vue DevTools. Jest to dodatek do zwykłych narzędzi programistycznych w przeglądarce, który pokazuje wszelkie przydatne informacje o komponentach – ich stanie, metodach, itd.
1. Zainstaluj Vetur oraz Vue DevTools.
2. Zapoznaj się ze strukturą plików projektu Vue.
W main.js ma miejsce inicjacja Vue i renderowanie App w naszej aplikacji w <div> w index.html. Ten plik nie będzie musiał się zmieniać.
import Vue from 'vue';
import App from './App.vue';
Vue.config.productionTip = false;
new Vue({
render: (h) => h(App),
}).$mount('#app');
Każdy z komponentów to zaledwie jeden plik *.vue, który zawsze składa się z trzech rzeczy:
<template>
<script>
<style>
<template></template>
<script>
export default {
name: 'nazwa-komponentu',
}
</script>
<style scoped></style>
Zazwyczaj znajduje się w pliku main.js. App to główny komponent aplikacji.
Vue tworzy drzewo wszystkich podkomponentów. Kiedy obliczy stan początkowy, umieszcza je w elemencie #app.
new Vue({
render: h => h(App),
}).$mount('#app')
Instancja Vue powinna wiedzieć, kiedy wykonać aktualizację komponentów w drzewie komponentów. Właściwość data mówi Vue o tym, które atrybuty powinny wywołać odświeżenie komponentu.
data: function() {
return { message: '' };
}
Gdy message ulegnie zmianie, Vue wyzwoli odświeżenie tego komponentu. Właściwości data są dostępne bezpośrednio pod this, np. this.message.
Metody są miejscem, gdzie zazwyczaj umieszczamy logikę dotyczącą zmian stanu komponentu.
Ten prosty komponent zlicza każde kliknięcie. Gdy klikamy, wywołujemy metodę onClick, która aktualizuje atrybut danych o liczbę kliknięć w przycisk. Gdy zmienna danych kliknięć zostanie zaktualizowana, Vue zauważy to i przeprowadzi ponowny rendering tego komponentu, a następnie wyświetli prawidłową wartość stanu tego komponentu.
Vue wykorzystuje składnię szablonów znaną z HTML, która jest całkiem potężna i eliminuje większość przypadków pisania kodu Javascript w szablonie.
W szablonie zapisujemy HTML z kilkoma dodatkowymi dyrektywami Vue i wiążemy elementy DOM z danymi Vue.
<div>
{{ message }}
</div>
Najbardziej podstawowym typem wiązania danych jest podwójny nawias, który służy do wyświetlania danych w DOM.
Kiedy chcemy powiązać pewną część danych z deklaracją komponentu lub elementu HTML w szablonie, używamy dyrektywy v-on.
<h1 v-on:title="title">
{{ message }}
</h1>
<!-- LUB W SKRÓCIE: -->
<h1 :title="title">
{{ message }}
</h1>
v-on informuje, że title jest elementem javascriptowym, który powinien znajdować się w znaczniku <script> komponentu. Dyrektywę v-on można zapisać w postaci skrótu – ":".
Dyrektywa v-model pozwala powiązać m.in. wartość pola tekstowego z właściwością danych komponentu.
Zmiana wartości pola tekstowego zmienia również wartość właściwości danych Vue, a dzięki reaktywności, zmiana ta pojawia się również w wyświetlanym tekście {{ name }}.
Kiedy chcemy zareagować na jakieś zdarzenie w DOM-ie, jak na przykład kliknięcie w coś, nasłuchujemy tego również za pomocą dyrektywy v-on. Dla zdarzeń ma ona jednak inny skrót: "@".
v-if i v-show to dwa różne sposoby decydowania, czy elementy powinny być przedstawione w interfejsie użytkownika. Ich kluczową różnicą jest to, że v-if usuwa element z DOM, gdy jest warunek fałszywy, natomiast v-show ustawia w CSS display: none.
<div v-if="count > 10">
Licznik jest większy od 10
</div>
<div v-else-if="count == 10">
Licznik jest równy 10
</div>
<div v-else>
Licznik jest mniejszy od 10
</div>
<div v-show="count > 10">
Licznik jest większy od 10
</div>
<div v-show="count == 10">
Licznik jest równy 10
</div>
<div v-show="count < 10">
Licznik jest mniejszy od 10
</div>
<!-- WYNIK DLA "count = 12": -->
<div>
Licznik jest większy od 10
</div>
<!-- POZOSTAŁE ELEMENTY -->
<!-- NIE SĄ RENDEROWANE -->
<!-- WYNIK DLA "count = 12": -->
<div>
Licznik jest większy od 10
</div>
<div style="display: none;">
Licznik jest równy 10
</div>
<div style="display: none;">
Licznik jest mniejszy od 10
</div>
v-for jest używane przy iteracji elementów w szablonie.
Klucz (key) powinien być podany, ponieważ Vue wiąże go z elementem DOM. Klucze muszą być unikalne dla danego elementu, a podanie niejednoznacznego klucza może spowodować błędy.
<div v-for="item in items" :key="item.id">
{{ item.name }}
</div>
<!-- Niezalecane, ale przy prostej iteracji dopuszczalne: -->
<div v-for="(item, index) in items" :key="index">
{{ item.name }}
</div>
1. Otwórz częściowo przygotowany projekt Vue.
2. Utwórz fork i zapoznaj się z jego plikami.
3. Przy pomocy v-for utwórz listę serwerów i zaimportuj komponent ServerList do komponentu głównego.
4. Wykorzystując obsługę zdarzeń, dodaj przycisk, który będzie dodawał do obiektu servers nowy element.
5. Do każdego serwera dodaj przycisk, który usunie konkretny serwer, a także przycisk, który zmieni jego status.
Gniazda (ang. slots) splatają zawartość komponentu nadrzędnego z szablonem komponentu potomnego, a tym samym ułatwiają dynamiczne aktualizowanie zawartości tych komponentów.
Slot to specjalny znacznik służący do oznaczania miejsca, w którym należy wstawić treści zapisane pomiędzy otwierającym a zamykającym znacznikiem komponentu.
Zazwyczaj aplikacja Vue jest zbudowana z wielu małych elementów, czyli z komponentów. Dość często przydaje się komunikacja pomiędzy komponentami. Istnieją 2 sposoby komunikacji – w górę i w dół.
Komunikacja w dół, to przesyłanie danych z komponentu nadrzędnego do komponentów potomnych przy użyciu propsów.
Komunikacja w górę, to przesyłanie danych przy pomocy zdarzenia z komponentu potomnego do komponentu nadrzędnego.
RODZIC
DZIECKO
WYEMITOWANIE ZDARZENIA
PRZEKAZANIE WŁAŚCIWOŚCI
1. Utwórz fork projektu z poprzedniego slajdu.
2. Do rozwijanego pola dodaj jako pierwszą opcję "-- Wybierz --". Zadbaj o to, by nie była ona brana pod uwagę przez aplikację podczas wyświetlania wybranego zwierzęcia.
3. Dodaj drugie pole rozwijane z listą ras. Lista ras powinna się zmieniać wraz ze zmianą zwierzęcia.
4. Aplikacja powinna wyświetlać informację o wybranym gatunku zwierzęcia oraz jego rasie.
Właściwości obliczane (ang. computed properties) to właściwości, które pozwalają uniknąć osadzania obliczeń bezpośrednio w kodzie szablonu.
Computed property zostanie ponownie obliczona tylko wtedy, gdy niektóre z jej zależności ulegną zmianie. Dla porównania, wywołanie metody będzie uruchamiać funkcję za każdym razem, gdy dojdzie do re-rendowania.
computed: {
getMessage() {
return this.message.firstname + ' ' + this.message.lastname;
}
}
computed: {
getFilteredArray() {
return this.array.filter(item => item.message === this.message);
}
}
We właściwościach obserwowalnych (ang. watch property), możemy "nasłuchiwać" zmian w danych, właściwościach obliczalnych lub w propsach. Kiedy ich wartość ulega zmianie, następuje wywołanie zwrotne.
watch: {
message(value) {
this.doStuff();
}
}
Kiedy właściwość message ulegnie zmianie, nastąpi wywołanie metody doStuff().
Każdy komponent ma swoją żywotność. Najczęściej używane punkty zaczepienia cyklu życia to:
W komponencie możemy nasłuchiwać tych punktów zaczepienia i kiedy one wystąpią, wykonać jakieś działania.
2. Stwórz komponent, którego przycisk będzie umożliwiał zmianę widoczności hasła, tj. zmieni typ pola z "password" na "text" i odwrotnie.
1. Stwórz komponent "Czytaj więcej...", który będzie rozwijał lub zwijał tekst.
1. Stwórz aplikację listy zakupów.
Celem tego projektu jest wypróbowanie różnych aspektów Vue i jednocześnie zbudowanie czegoś użytecznego. W tym projekcie omówimy:
Projekt ten składa się z kilku etapów, a jego wynikiem będzie aplikacja pogodowa.
Projekt do danych o pogodzie będzie wykorzystywał API.
API (ang. Application Program Interface) to zestaw funkcji i procedur, które pozwalają na tworzenie aplikacji, które uzyskują dostęp do danych i funkcji innych aplikacji, usług lub systemów.
JSON (ang. JavaScript Object Notation) to standard formatu tekstowego do reprezentowania danych strukturalnych, który jest oparty na składni obiektowej JavaScriptu. Używany jest przede wszystkim do przesyłania danych pomiędzy serwerem a aplikacją internetową, często jako alternatywa dla XML.
"foo" : {
"bar" : "Hello",
"baz" : ["quuz", "norf"]
}
// Wstępne kroki
Pierwszym krokiem jest stworzenie listy miast, dla których będzie można pobrać pogodę. Aby utworzyć tę listę, potrzebujemy pola wejściowego z przyciskiem do dodawania nowych miast do listy miast.
// Lista miast
Oczekiwany rezultat:
Wskazówki:
W tej części pobierzemy pogodę z OpenWeatherApi i przechowamy ją w naszym stanie komponentu zamiast tylko nazwy miasta. Integracja API została już stworzona, musisz tylko dodać klucz API w pliku /src/util/Api.js. Następnie należy pobrać pogodę dla dodanych miast.
// Integracja z API
Oczekiwany rezultat:
Wskazówki:
import * as Api from "./util/Api"; // Użycie: Api.getCurrentWeather();
Tym razem zadaniem jest zapisanie listy miast do lokalnego magazynu użytkownika (localStorage), po to, by użytkownik, gdy opuści aplikację i na nią wrócić po jakimś czasie, otrzymał listę swoich miast. Integracja z localStorage jest już utworzona.
// Zapisanie listy
Oczekiwany rezultat:
Wskazówki:
// Routing
<router-link :to="`/city/${city.id}`">{{ city.name }}</router-link>
Oczekiwany rezultat:
Wskazówki:
W ostatniej części nie krępuj się bawić z Vue i być kreatywnym. Ostyluj swoją aplikację i dodaj niezbędne elementy na podstronie miasta.
// Ostatnie szlify
Pomysły do realizacji:
Wyświetlenie nazwy miasta;
Aktualna temperatura dla pojedynczego miasta po środku strony;
Wyświetlenie listy prognoz na najbliższe 5 dni na dole strony;
W zależności od pogody (weather.main w API), wyświetlenie w tle odpowiedniego obrazu, np. pochmurne niebo.
Wskazówki:
Zacznij od utworzenia forka (kopię) projektu. By zapisać swój projekt i móc realizować inne ćwiczenia w CodeSandbox, załóż konto.
Ćwiczenie 3.4
Właściwość servers to tablica składająca się z wielu obiektów. By móc do niej dodać kolejne elementy, zapoznaj się z funkcją push().
Aby usunąć konkretny element tablicy, możesz skorzystać z funkcji splice() oraz indexOf().
Warto też przypomnieć sobie w jaki sposób odwołujemy się do właściwości obiektów w JavaScript.
Obsługę zdarzenia kliknięcia w przycisk znajdziesz w tym slajdzie.
Po pierwsze, należy dodać nowy element <option> w komponencie AnimalList wewnątrz rozwijanego pola <select>. Nowa pozycja nie powinna być brana pod uwagę przez komponent, zatem należy ją wykluczyć warunkiem wewnątrz metody onSelect().
Ćwiczenie 3.5
Po drugie, trzeba dodać nowe tablice z rasami zwierząt wewnątrz data. Ewentualnie można również przerobić aktualną tablicę na obiekt z tablicami wewnątrz.
Ostatnią czynnością jest dodanie komponentu DropDown z nowymi tablicami i wyświetlanie ich w zależności od aktualnie wybranego gatunku zwierzęcia, np. poprzez v-if.
Do uzyskania efektu z tego ćwiczenia, możesz wykorzystać dodatkowe znaczniki HTML wewnątrz akapitu z tekstem, np. span:
Ćwiczenie 3.6.1
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum iste <span class="dots">...</span>
<span class="more">iusto magni voluptas impedit vitae neque aut eaque repudiandae laboriosam in,
minima totam animi sunt aliquam? Architecto at esse labore?</span>
</p>
Następnie wystarczy utworzyć zmienną, która będzie przechowywała aktualny status (rozwinięte / zwinięte) i na tej podstawie decydować o tekście, np. poprzez dyrektywę v-show.
data: () => ({
more: false,
})
Do zdarzenia @click przycisku można podpiąć metodę zmieniającą status tej zmiennej.
Zacznijmy od struktury HTML: musi ona zawierać pole oraz przycisk.
Ćwiczenie 3.6.2
<div class="input">
<input placeholder="Wprowadź hasło...">
<button><img src="../assets/eye.png"></button>
</div>
Następnie dobrze byłoby dodać właściwość ze statusem podglądu:
data: {
showPassword: false,
},
Teraz, w zależności od statusu, wystarczy przy pomocy dyrektywy :type określić rodzaj pola, a w przypadku przycisku, ścieżkę do obrazka dyrektywą warunkową v-show.
Darmowe ikony do tego ćwiczenia w formacie *.PNG znajdziesz na https://remixicon.com/ ("eye" oraz "eye-off").
Struktura HTML powinna zawierać zwykłą listę <ul> wraz z dyrektywą v-for, która będzie iterować elementy <li>, np.
Ćwiczenie 3.7
<ul>
<li v-for="(item, index) in items" :key="index">
{{ item }}
</li>
</ul>
Aby móc określić konkretny element listy jako "zakupiony", można skorzystać z tablicy obiektów:
data:{
items: [
{name: 'Banany', checked: false},
{name: 'Truskawki', checked: false},
{name: 'Jabłka', checked: false},
],
}
Do powiązania właściwości checked z checkboxem wystarczy skorzystać z dyrektywy v-model:
<input type="checkbox" value="" v-model="item.checked">
<input v-model="newItem" placeholder="Wprowadź nazwę..." @keyup.enter="addItem">
Obsługa zdarzenia wciśnięcia klawisza enter w polu tekstowym: