Ostatnim razem opisałem podstawy projektowania komponentów w aplikacjach budowanych za pomocą biblioteki Vue. Myślę, że udało si mi pokazać, że mechanizm ten daje ogromne możliwości oraz, że warto go poznać.
Dziś pociągnę temat dalej i przedstawię sposoby na to jak całkowicie oddzielić komponenty od instancji Vue. Kolejnym krokiem będzie dynamiczne dostarczanie danych dla komponentów, co jeszcze bardziej ożywi budowane aplikacje.
Tak jak w poprzednim wpisie, zaczynam od dokumentu HTML zawierającego taki oto element body:
1 2 3 4 5 6 7 8 9 |
<body> <div id="vueApp"> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script> <script type="text/javascript" src="app.js"></script> </body> |
Treść biblioteki dołączona jest z CDNu, a mój przykładowy kod znajduje się w pliku app.js.
Czas na zdefiniowanie komponentu. Tym razem nie chcę robić tego w głównej instancji Vue. Mam możliwość inicjalizacji komponentów niezależnie i chcę z tej możliwości skorzystać. Dzięki temu komponent mógłbym ostatecznie trzymać w osobnym pliku i wykorzystywać wielokrotnie. To bardzo przydatne!
Ten kod dodam do pliku app.js:
1 2 3 |
Vue.component('my-header', { template: '<h2>Welcome</h2>', }) |
Jak widać stworzenie niezależnego komponentu to nic trudnego. Po prostu wywołuję metodę component głównego obiektu Vue. Przyjmuje ona dwa argumenty. Pierwszy to nazwa tworzonego komponentu a drugi to obiekt z opcjami, dokładnie takimi jak zwykle. W tej chwili wewnątrz opcji umieszczam tylko jedno pole, znany już template, w którym definiuję widok komponentu. na początku jest to tylko prosty nagłówek.
W takiej formie oczywiście komponent nie zadziała, muszę dodać stworzyć główną instancję Vue. Nie jest to jednak nic trudnego, należy tylko pamiętać o jednej rzeczy. Wszelkie definicje komponentów muszę zostać zadeklarowane przed główną instancją. W moim przypadku cały kod jest w jednym pliku, ale w prawdziwym projekcie, komponenty znajdować się będą w osobnych plikach. Aby wszystko działało jak trzeba, muszą one być dodane do dokumentu przed kodem z główną instancją Vue.
Kompletny plik app.js wygląda tak:
1 2 3 4 5 6 7 |
Vue.component('my-header', { template: '<h2>Welcome</h2>', }) var vueApp = new Vue({ el: '#vueApp', }) |
Teraz w dokumencie HTML wystarczy dodać tag z nowo utworzonym komponentem:
1 2 3 |
<div id="vueApp"> <my-header></my-header> </div> |
Budowanie komponentów, które można używać wielokrotnie jest, jak widać, bardzo łatwe w bibliotece Vue. Jednak aby w pełni móc korzystać z dobroci komponentów, brakuje jeszcze jednej rzeczy, mianowicie sposobu na przekazywanie danych z głównego widoku.
Najprostszym sposobem aby to osiągnąć, jest wykorzystanie tak zwanych rekwizytów (od angielskiego props). Ja będę mówił na te element propsy 🙂 . Czym są propsy i jak można je wykorzystać. Spójrzmy na przykład:
1 2 3 4 |
Vue.component('my-header', { props: ['user'], template: '<h2>Welcome {{ user }}</h2>', }) |
W komponencie dodałem nowe pole props, jego zawartość to tablica, zawierająca definiowane przez nas nazwy propsów. Tak zdefiniowany props mogę użyć wewnątrz template’a komponentu. Wpisuję go jak każdą zmienną w widoku, otoczonego podwójnymi nawiasami wąsatymi.
Teraz mogę użyć propsa. Aby móc z niego korzystać wystarczy, że nadam mu wartość w widoku:
1 2 3 |
<div id="vueApp"> <my-header user="John"></my-header> </div> |
Mój props user, mogę teraz dodać jako atrybut mojego komponentu w widoku. Przekazana wartość będzie wartością propsa użytego w templacie.
Po uruchomieniu tego kodu w przeglądarce zobaczymy napis „Hello John”.
Ostatecznie jednak chcę do propsa przekazać dane z głównej instancji Vue. W końcu do tego służy. Oto jak wygląda aktualnie cała treść app.js:
1 2 3 4 5 6 7 8 9 10 11 |
Vue.component('my-header', { props: ['user'], template: '<h2>Welcome {{ user }}</h2>', }) var vueApp = new Vue({ el: '#vueApp', data: { userName: "John", } }) |
Chcę aby zawartość zmiennej userName (która mogła zostać wczytana z serwera bo zalogowaniu się użytkownika), wyświetliła się wewnątrz komponentu.
Pierwszą myślą jaka przyjdzie do głowy jest wpisanie jej w wąsatych nawiasach jako wartość atrybutu userName. To jednak nie zadziała, komponent ma swój własny zakres i nie zrozumie nazwy zmiennej.
Aby osiągnąć mój cel, muszę użyć dyrektywy v-bind:
1 2 3 |
<div id="vueApp"> <my-header v-bind:user="userName"></my-header> </div> |
Dzięki takiej operacji do propsa user trafia odpowiednia wartość.
To wszystko na dziś. W kolejnym poście postaram się zebrać to wszystko do kupy i napisać jakiś większy przykładowy komponent. Jeśli nie chcesz żądnego posta, zachęcam do polubienia mojej strony na facebooku. Zawsze zamieszczam tam informacje o wszystkich nowościach. Jest to też dobre miejsce na kontakt ze mną. Na wszystkie pytania zawsze odpowiem :).