Piszemy aplikację we Vue.js - cz. 1.

Ładniej sformatowany tekst znajdziesz na moim blogu.

Vue.js jest lekkim, szybkim i bardzo łatwym w nauce frameworkiem (pod warunkiem, że znamy co najmniej podstawy JS). Chcę Ci pokazać jak szybki i łatwe może być pisanie reaktywnych aplikacji.

Cała seria wpisów będzie się składać z co najmniej 10 krótkich części, a efektem finalnym będzie kompletna aplikacja wyświetlająca listę ogłoszeń wraz z logowaniem (opartym na localStorage).

Pierwszy komponent

Jednak zanim zbudujemy swój pierwszy komponent musimy przygotować środowisku. Z pomocą przychodzi społeczność i przygotowany Vue-cli. W pierwszych projektach korzystałem z browserify, jednak w najnowszym przesiadłem się na webpack, który domyślnie nie obsługuje np. scss.

Skoro mamy skonfigurowane środowisku i utworzony nowy projekt możemy przystąpić do napisania pierwszego komponentu. Nie będę Cię męczył Hello World bo to znajdziesz w dokumentacji. Zaczniemy od większej rzeczy - strona główna z listą ogłoszeń, nagłówek z nawigacją i stopka. Uprzedzam, że na ten moment ignoruję design, a skupiam się na działaniu.

Słowem wspomnę tylko o strukturze plików. Vue nie narzucam nam z góry określonej struktury. Dla swoich projektów dostosowuję strukturę na bieżąco w trakcie pisania, ale zaczynam zawsze tak:


|- src
    |- components
        |- Nav.vue
        |- Header.vue
        |- Footer.vue
    |- scss
    |- views
        |- Homepage.vue
    |- store
    |- main.js
|- dist
    |- style.css
    |- main.js
|- index.html

W pliku index.html trzymam tylko i wyłącznie linkowanie do css i js, meta tagi, fonty (z google fonts) oraz kontener aplikacji.


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mavenet.me</title>
        <link rel="stylesheet" href="dist/styles/main.css">
        <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
        <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=yes" />
  </head>
  <body>
    <div id="app">  
        <router-view></router-view>
    </div>
    <script type="text/javascript" src="dist/main.js"></script>
    <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700&amp;subset=latin-ext" rel="stylesheet">
  </body>

Natomiast src/main.js zawiera wszystko co potrzebne do odpalenia vue oraz moduły, które wykorzystujemy w całej aplikacji


import Vue from 'vue';
import VueRouter from 'vue-router';
import Homepage from './views/Homepage.vue';

Vue.use(VueRouter); 

const routes = [ 
    { path: '/', component: Homepage },
]
const router = new VueRouter({
    routes
}) 
new Vue({
    router
}).$mount('#app')

Jak wspomniałem na początku - pominiemy etap Hello World i wchodzimy do brodzika ;) Nasz pakiet startowy zawiera:
- vue.js
- vue-router
- skonfigurowany routing na stronę główną
- komponent strony głównej wraz z komponentami Nav, Header, Footer.

Homepage.vue


<template>
    <div>
        <header-component></header-component>
        <main>
            // lista ogłoszeń
        </main>
        <footer-component></footer-component>
    </div>
</template>

<script>
    import FooterComponent from '../components/Footer.vue';
    import HeaderComponent from '../components/Header.vue';

    export default {
        name: 'app',
        components: {
            FooterComponent,
            HeaderComponent
        },
        data() {
            return {
                items: [
                    {
                        username: 'HitcH',
                        voice: 'is-active',
                        status: 'online',
                        opinion: 4,
                        opinionCount: 15,
                        game: {
                            name: 'World of Tanks',
                        },
                        when: {
                            from: '18:30',
                            to: '21:25'
                        }                    
                    },
                    {
                        username: 'Klamca',
                        voice: 'is-optional',
                        status: 'busy',
                        opinion: 2,
                        opinionCount: 15,
                        game: {
                            name: 'Overwatch',
                        },
                        when: {
                            from: '18:30',
                            to: '21:25'
                        }
                    }
                ]
            }
        },
        computed: {

        },
        methods: {

        }
    }
</script>

Wyjaśniając dlaczego HeaderComponent i FooterComponent -> header i footer są tagami HTML i nie możemy ich wykorzystać jako nazwy komponentów. Załadowałem przykładowe dane, który wykorzystamy do wyświetlania listy.


<div v-for="item in items">
    {{ item.username }} is {{ item.status }}, {{ item.when.from }} - {{ item.when.to }}<br>
    He plays {{ item.game.name }}
</div>

Jak widzisz jest prosto, bardzo prosto. Każda zmienna jest pomiędzy {{ }}, a do iteracji służy v-for. Po zapisaniu plików i skompilowaniu Twoim oczom powinna ukazać się lista 'ogłoszeń', oczywiście będzie brzydko, ale zawsze możesz wrzucić Bootstrapa ;) (którego osoboście nie trawię).

W następnej części zrobimy komponent Header wraz z nawigacją (która będzie naszym pierwszym reużywalnym komponentem).