Prosty i Nowoczesny Framework dla Vue.js
7 godz. 2 min · Vue.js · Full-stack i Programowanie
Wojciech PołowniakSr. Fullstack EngineerW tym projekcie tworzyć będziemy praktyczny projekt - klona Wikipedii! Minipedia pobierze dane z prawdziwego źrodła danych, zewnętrznego API WikiMedia - będzie łudząco podobna do oryginału oraz współdzieliła najważniejsze funkcjonalności, takie jak dostarczanie treści w różnych wersjach językowych, możliwość wyszukiwania artykułów, czy pobieranie najpopularniejszych wpisów dla danego języka. Stworzymy także podstronę wyświetlającą za każdym razem losowy artykuł w danej wersji językowej.Zobaczysz też, jak dokonać migracji ze statycznej strony HTML na Nuxt - oraz jak tworzyć przykładowe komponenty podczas tego procesu.Dzięki temu wszystkiemu, dowiesz się jak wykorzystać nabytą wiedzę w praktyce.
Dzięki Nuxtowi dowiesz się jak optymalizować Twoje strony www z duchem idei progressive enhancement, dostarczając coraz to lepsze doświadczenia dla swoich użytkowników oraz tworząc aplikację napisaną w 100% w JavaScript, która będzie działała nawet wtedy, gdy użytkownik jawnie wyłączy go w przeglądarce! To wszystko za SSR (Server Side Rendering), dzięki któremu treści będą gotowe do konsumpcji już przy wstępnej, pierwszej odpowiedzi z serwera WWW.Oczywiście, ma to swoje implikacje na wydajność naszej aplikacji - sprawiając że Lighthouse czy optymalizacja pod SEO staje się coraz prostsza!
Czymże jest ekosystem danego frameworka bez wsparcia społeczności! Dlatego podczas tego kursu nauczysz się instalować i wykorzystywać różne pluginy i moduły, które zaoszczędzą Ci dużo czasu. Dowiesz się też, jak tworzyć własne moduły - które rozszerzą działanie Twojej aplikacji Nuxt w sposób czysty i zarządzalny.
Nuxt jest frameworkiem w którym pracujemy zarówno po stronie front-endu, jak i back-endu. W związku z czym, stworzymy swoje własne API (bazujące na express.js) które będzie pewnego rodzaju pośrednikiem pomiędzy API WikiMedia oraz Twoją aplikacją internetową.
W tym kursie, dowiesz się także jak tworzyć swoje własne Middleware'y - czyli fragmenty kodu wywoływane pomiędzy przechodzeniem między stronami, czy podczas innych zapytań HTTP.Dodatkowo, zobaczysz jakie narzędzia daje nam Nuxt aby tworzyć progresywne aplikacje internetowe, oferując wsparcie dla takich funkcjonalności jak np. animacje między przejściami pojedynczymi podstronami naszego serwisu.
Tajemnicze i18n - czyli numeronim odpowiadający angielskiemu słowu "internalisation" - odnosi się w kontekście web developmentu do tłumaczenia danych na różne języki. Podczas realizacji projektu Minipedii, nie tylko wykorzystamy standardowe podejście do tłumaczeń stałych elementów naszego interfejsu użytkownika, ale także przetłumaczymy same dane zwracane z API, wykorzystując inną wersję językową w zależności od preferencji użytkownika!
Poznasz też kilka ciekawych pluginów i rozwiązań dotyczących optymalizacji pod SEO - poza faktem, że podejście spełniające intencje użytkownika jest najlepszym, co możemy zrobić - pluginy generujące nam mapę stron automatycznie na podstawie zadeklarowanych przez nas podstron, czy generatory danych jsonld pomogą w pozycjonowaniu Twojej wydajnej aplikacji jeszcze wyżej w hierarchii wyszukiwarek.
Aby móc efektywnie korzystać z tego kursu, powinieneś posiadać średnio zaawansowaną wiedzę z kategorii Front End, z naciskiem na umiejętność posługiwania się JavaScriptem oraz solidne podstawy NodeJS. Konieczna jest znajomość Vue, jako że Nuxt jest frameworkiem korzystającym z niego u swoich podstaw. Jeśli czujesz się dość swobodnie w wyżej wymienionych aspektach web developmentu, ten kurs będzie idealny dla Ciebie.
Cześć! W poprzedniej lekcji stworzyliśmy
komponent Content Section, który wyświetla nam pojedynczą sekcję i
dzięki temu możemy wyświetlać różną treść na naszej stronie Wikipedii.
To co będziemy robić teraz, to jest spis
treści i spis treści będzie całkiem analogiczny do tego, co już zrobiliśmy.
Różnicą jest to, że w naszym katalogu pages index.
Po pierwsze troszkę zmienimy to, co już
stworzyliśmy, czyli nie będziemy tutaj pikować tej treści, tylko faktycznie
wrzucimy ją w pętlę i zmodyfikujemy nasze komputer Properties.
W taki sposób, aby nie nazywało się bibliografii, tylko po prostu content.
I będzie to zwracało tablicę, czyli.
Jeśli tutaj nam się kończy nasza treść.
Jeśli dobrze myślę, tutaj jest koniec treści.
Znajdźmy.
Odpowiedni.
Natomiast tutaj wstawiamy jeszcze jeden.
Jeśli się nie mylę, nawiasy kwadratowe.
I w tym momencie mamy tutaj tablicę.
Takich obiektów będziemy mogli definiować
sobie różną treść w zależności od tego, co tutaj wstawimy.
Czy jeśli ja sobie skopiuję title i content i dopisze na samym końcu?
Powiedzmy tutaj.
Nowy obiekt i tutaj wpisujemy treść.
Hello world zapiszemy.
I oczywiście aplikacja w tym momencie może
przestać działać, ponieważ pozbyliśmy się naszego.
W bibliografii.
Tyle grafik przepraszam, a dalej się do niej odnosimy poprzez.
Nasze komponenty.
Widzę, że coś tutaj się chyba nie
odświeżyła, więc ja zrestartuje tylko szybciutko serwer.
Chyba po odświeżeniu tak.
Więc tutaj.
Uruchomimy go jeszcze raz.
I w tym momencie pojawia się błąd, że
w biografii nie jest zdefiniowane, chyba że w międzyczasie zdążymy to naprawić.
Czyli to, co powinniśmy robić, to tak
naprawdę albo na komplecie, albo na samym komponencie zrobić via fora.
I tutaj analogicznie do tego, co tworzyliśmy wcześniej.
Ustawić powiedzmy for.
Section in content.
Renderować sam komponent.
Tutaj widzimy, że się zepsuło.
Czego się moglibyśmy spodziewać?
Pozbędziemy się tych dodatkowych komponentów?
I po prostu podmieniamy.
W geografii na.
Section.
Przy okazji fajnie zawsze zobaczyć, że Next ma taki ekran ładowania
tego co się dzieje, nawet jeżeli aplikacja nie działa.
Tutaj zabrakło nawiasu.
Niestety na małych ekranach można się pogubić.
Wpiszmy jeszcze raz token.
Jak by tutaj to sprawdzić.
Moglibyśmy rozwinąć to jeżeli nam pozwoli
edytor kodu, ale on tylko i wyłącznie pierwszą sekcję.
Więc po prostu może go chwilowo usuniemy.
Tutaj przyciągniemy.
Pozbędziemy się sekcji treści.
I teraz będzie o wiele łatwiej zauważyć co jest nie tak.
Czyli tutaj mamy poprawny obiekt z contentem jako tablicą.
To jest wszystko jak najbardziej w
porządku i ten element nie ma tutaj zamknięcia.
Tablicę oczywiście.
Więc w tym momencie prawdopodobnie sekcja będzie pusta.
Oczywiście biografia jest pusta, więc możemy teraz wkleić z powrotem tą treść.
I uzupełnić tę Reiko.
Więc w tym momencie nasza aplikacja działa dokładnie tak samo, tylko z innego miejsca
pobiera dane i to też będziemy robić w następnych lekcjach.
Po prostu podmieniać to z Computer
properties na inne właściwości, które będą szły z API.
No i jak to się ma do spisu treści?
Dzięki temu, że mamy content zdefiniowany
w jednym kompie to jest property, które nazywa się właśnie content.
Będziemy w stanie stworzyć blok content dynamicznie.
Czyli ja sobie to skopiuje.
Stworzy nowy komponent.
Table of Contents.
Kropka view.
Możemy skopiować sobie tutaj content section.
I podmienić jego treść.
Na to co tam.
Zadeklarowaliśmy.
Więc content możemy zostawić, jako że jest
to nagłówek i będziemy dynamicznie generować tutaj te oto linki.
Czyli jeżeli ja to napiszę i pozbędę się w tym momencie procesów,
albo je zmodyfikuję, czyli weźmiemy tutaj po prostu content.
Jako.
Trójkę zapiszemy i wyświetlając to w tym miejscu, czyli tabelę o contents.
Ustawiamy content na cały content.
Zapiszemy, zobaczymy, że ten komponent da się wyrenderować.
On oczywiście jeszcze nic nie robi.
To są dalej za hard kodowane dane, ale jak widzimy tutaj z biografii Riding itd.
My mamy tylko i wyłącznie gaz.
Więc ta sekcja może zostać zmieniona w
taki sposób, aby była też sekcją dynamiczną.
Czyli tutaj to wyrównane, pozbędziemy się dodatkowych punktów.
W tym momencie już nie będziemy potrzebowali i w for.
Section content, czyli dla każdego elementu, który jest przekazywany w
procesach poprzez content będziemy go renderować, czyli content.
Kropka.
Bo tutaj indeks kropka.
Jak wejdziemy w content to widzimy, że to jest tablica obiektów,
które zawierają w sobie title oraz content.
I w tym momencie to jest puste.
Jest w sumie ciekawe dlaczego?
Czy jest to kwestia pensji, czy jest to kwestia tego co jest tam przekazywane?
Definitywnie są tam dwa elementy.
Może jest jakaś literówka content type?
Content type.
Wygląda to zdrowo.
Możemy cały.
Cały nasz content.
Wyświetlić a content.
Oczywiście nie ma takiego wpisu, ale jest zasięg.
Kontent jest to nasz proces, a nie pojedynczy element wewnątrz tego procesu.
I jak widzimy w tym momencie już mamy
odnośniki, które generują się na podstawie treści, którą zdefiniowaliśmy tutaj.
I to jest po pierwsze cała siła WP,
że jesteśmy w stanie w taki sposób deklarować nową
treść i różne komponenty mogą się aktualizować równolegle do siebie.
Czyli jeśli tutaj dodam.
Right X i Hello World 2. Zapiszemy na to.
Oczywiście oba komponenty się aktualizują, czyli tutaj doszły nam rating i tutaj
doszła sekcja rating, ale co istotne nie działają nam jeszcze sam odnośnik,
ponieważ tutaj jeżeli klikniemy biografii to faktycznie działa.
Ponieważ to był domyślny odnośnik, ale nie
przenosi nas to do sekcji sam wygasa i waiting, więc to jeszcze zrobimy.
I aby taka nawigacja działała to musimy
zrobić kotwicę i wyrenderować odpowiedni identyfikator przy danej sekcji.
Czyli musimy przejść do komponentu content
section i tutaj upewnić się, że H2 będzie miało odpowiedni identyfikator.
Jak możemy to zrobić?
Ja bym stworzył metodę.
Która nazywa się Podsumuję.
Może to być komplet.
Chyba będzie to prostsze.
Czyli komputer.
Ustawimy na.
Healing it.
I to będzie nam zwracało.
Dis props site.
I w tym momencie będziemy mogli użyć go.
Na naszym widoku, czyli tutaj możemy sobie zrobić Healing ID.
Zapiszemy. Oczywiście będzie się to wyświetlało
jakoś brzydko, ale faktycznie się wyświetla i
ważne jest to, że ta informacja będzie wewnątrz tutaj atrybutu html owego.
Czyli najlepiej byłoby, gdyby ta wartość była jakoś znormalizowane,
czyli nie byłoby tam spacji, nie byłoby tam specjalnych znaków
czy nawet wielkich liter, więc możemy tutaj zrobić height
i to co jeszcze można zrobić to po prostu replace.
Wszystkie spacje na pustego stringa
albo na myślnik, jeżeli chcemy zachować czytelność.
I następnie tu lower
case, które jest standardową metodą na wszystkich stringach w skrypcie.
Więc jeśli teraz zerkniemy na nasz nagłówek
biografii, to widzimy, że on ma tutaj odnośnik biografii.
Tak naprawdę nie jest to.
Odnośnik tylko identyfikator.
I tutaj tak samo sam Fingers.
Działa, więc to widać property.
Ono będzie dosyć podobne w obu sekcjach.
Moglibyśmy to jakoś ujednolicić, aby nie kopiować kodu w te i wewte.
Ale nie to jest celem tej lekcji.
Więc tutaj sobie zapiszemy i możemy użyć tego zamiast jedynki.
Możemy wykorzystać tutaj section id
i zamiast props title, no bo oczywiście takiego tutaj nie mamy.
Będziemy musieli przekazać pojedynczą
sekcję, więc być może w tym momencie lepiej jest wykorzystać do tego
i tutaj przekazać po prostu konkretną sekcję, na której pracujemy.
I na tej sekcji mamy.
Ponieważ tutaj renderuje i seks section tytuł.
Tak samo pasujemy do jakiegoś wspólnego mianownika.
Po zapisaniu musimy oczywiście
podpiąć tę wartość pod nasz znacznik odnośnika pod atrybut y.
Jednak zanim to nastąpi, być może
darujmy sobie tylko faktycznie tę wartość, czyli jest to
metoda Section id i tutaj przekazujemy sekcję.
Moglibyśmy zmienić nazwę tej
funkcji, żeby brzmiała jak faktycznie coś, co jest funkcją, a nie property.
I widzimy, że faktycznie przed treścią
w naszym content znajduje się zunifikowany identyfikator danego
nagłówka, czyli to, co pozostaje na zrobić to poza zmianą nazwy tej funkcji get
section id to przypisać ją do atrybutu i tutaj możemy
po prostu poprzedzić ją hashtagiem tak aby to była kotwica html owa.
I tutaj template stringi z JavaScriptu, aby dostać się do wartości tej zmiennej.
Czyli po prostu przekazujemy to tutaj.
Pozbywamy się wąsów, jeśli nie są już potrzebne.
Jeśli wszystko poszło dobrze to powinno nas to przekierowywać
na odpowiednie sekcje i tak się faktycznie dzieje.
Jeżeli klikniemy biografię to widzimy, że biografia jest na samej górze.
Są fingers i są fingers jest na samej górze.
Analogicznie do writing też możemy przejść.
Jeżeli dana sekcja znajdowałyby się dosyć
nisko strony, to oczywiście ona się może zatrzymać troszkę wcześniej, ponieważ
scroll nam po prostu tak daleko nie dojedzie.
Ale tym oto sposobem stworzyliśmy.
Dwa komponenty, już, które współistnieją ze sobą, mają wspólne źródło
danych i adaptując jedno miejsce w naszej aplikacji zmienia się cała jej struktura.
Czyli wystarczy zmienić w jednym miejscu np.
tytuł naszej sekcji na powiedzmy filtr.
Choć i po zapisaniu zarówno tej below
contents jak i cała sekcja ulegnie zmianie.
I tak jak na początku możemy korzystać z tego komponentu
globalnie, ponieważ zadeklarowaliśmy je w katalogu components.
W kolejnej lekcji zajmiemy się sekcją z głównymi informacjami.
Tak jak mówiłem troszkę ją pewnie wytniemy
z funkcjonalności i będzie to koniec tego działu i w następnych działach zaczniemy
się zajmować bardziej backend ową częścią pracy z pakietem.
Zmiany wprowadzone w lekcji · 13 min
diff --git a/08/minipedia/components/ContentSection.vue b/08/minipedia/components/ContentSection.vue
index e631984..2c93545 100644
--- a/08/minipedia/components/ContentSection.vue
+++ b/08/minipedia/components/ContentSection.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <h2 id="biography">{{ $props.title }}</h2>
+ <h2 :id="headingId">{{ $props.title }}</h2>
<p v-for="paragraph in content">
{{ paragraph }}
</p>
@@ -19,6 +19,11 @@ export default {
required: true,
}
},
+ computed: {
+ headingId() {
+ return this.$props.title.replace(' ', '-').toLowerCase();
+ }
+ }
}
</script>
diff --git a/08/minipedia/components/TableOfContents.vue b/08/minipedia/components/TableOfContents.vue
new file mode 100644
index 0000000..0798189
--- /dev/null
+++ b/08/minipedia/components/TableOfContents.vue
@@ -0,0 +1,35 @@
+<template>
+ <div>
+ <div class="toc">
+ <div class="box">
+ <h2 class="no-underline"> Contents </h2>
+ <ol>
+ <li v-for="section in content">
+ <a :href="`#${getSectionId(section)}`">
+ {{ section.title }}
+ </a>
+ </li>
+ </ol>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ props: {
+ content: {
+ type: Array,
+ required: true,
+ }
+ },
+ methods: {
+ getSectionId(section) {
+ return section.title.replace(' ', '-').toLowerCase();
+ }
+ }
+}
+</script>
+
+<style>
+</style>
diff --git a/08/minipedia/pages/index.vue b/08/minipedia/pages/index.vue
index 3537ee5..22e0a32 100644
--- a/08/minipedia/pages/index.vue
+++ b/08/minipedia/pages/index.vue
@@ -55,29 +55,10 @@
was sent from the Ghetto to the Treblinka extermination camp by the Nazis, during the Grossaktion
Warschau of 1942.</p>
- <div class="toc">
- <div class="box">
- <h2 class="no-underline"> Contents </h2>
- <ol>
- <li><a href="#biography">Biography</a></li>
- <li><a href="#writings">Writings</a></li>
- <li><a href="#legacy-and-remembrance">Legacy and remembrance</a></li>
- <li><a href="#list-of-selected-works">List of selected works</a></li>
- <li><a href="#in-popular-culture">In popular culture</a></li>
- <li><a href="#notes">Notes</a></li>
- <li><a href="#references">References</a></li>
- <li><a href="#further-reading">Further reading</a></li>
- </ol>
- </div>
- </div>
-
- <ContentSection :title="biography.title" :content="biography.content" />
-
- <ContentSection :title="biography.title" :content="biography.content" />
-
- <ContentSection :title="biography.title" :content="biography.content" />
-
- <ContentSection :title="biography.title" :content="biography.content" />
+ <TableOfContents :content="content" />
+
+ <ContentSection
+ v-for="section in content" :title="section.title" :content="section.content" />
<h2 id="references">References</h2>
<ol class="references">
@@ -232,8 +213,8 @@
export default {
layout: 'default',
computed: {
- biography() {
- return {
+ content() {
+ return [{
title: 'Biography',
content: [
`Korczak was born in Warsaw in 1878. He was unsure of his birth date, which he attributed to his
@@ -287,7 +268,18 @@
after a brief stint in Łódź was assigned to Warsaw. After the wars, he continued his practice in
Warsaw.`
]
+ },
+ {
+ title: 'Childhood',
+ content: ['Hello world']
+
+ },
+ {
+ title: 'Writings',
+ content: ['Hello world2']
+
}
+ ]
}
}
}