Vue.js alkuun pääseminen

npm install vue @vue/cli -g
vue create <hakemisto>

tai käyttäen graafista käyttöliittymää

vue ui
npm run serve

Kehitystyökalut

Esimerkiksi

Vue-komponenttien rakenne

vue-cli teki projektiin pari *.vue-tiedostoa. Ne ovat vue-komponentteja. Komponentit koostuvat kolmesta osasta. Template on ulkoasun/käyttöliittymän rakenne eli (yleensä) html:ää, script on koodia (ES2015+) ja style tyylimäärittelyt (css).

Templatessa saa olla vain yksi juurielementti

<template>
    <span>{{ message }}</span>
</template>
<script>
    export default {
        data() {
            return {
                message: 'Hello vue.js'
            }
        }
    }
</script>
<style scoped>
    span {
        font-weight: bold;
    }
</style>

Halutessaan komponentin voi jakaa eri tiedostoihin laittamalla src -attribuutin

<template>
    <span>...</span>
</template>
<script src="./component.js">
</script>
<style scoped>
    /* ... */
</style>

Tekstikentät ja arvojen näyttäminen

Syötetään ja tulostetaan nimi (yksirivinen, plain text) ja kuvaus (monirivinen, mahdollisesti html:ää)

export default {
    data() {
        return {
            name: '',
            description: ''
        }
    }
}

Input-elementtiin arvon saa sidotua v-model -attribuutilla. Sidonta toimii kahteen suuntaan eli datan päivittyessä input päivittyy ja toisinpäin.

<input type="text" v-model="name" />

Sama toimii myös textareassa

<textarea v-model="description" rows="5"></textarea>

Arvojen tulostamiseen käytetään {{ lauseke }} -syntaksia

<span>{{ name }}</span>

Tämä enkoodaa mahdollisen html-sisällön. Jos html:n haluaa näyttää sellaisenaan, käytetään v-html -attribuuttia.

<p v-html="description"></p>

Radiobutton

Valitaan rooli kolmesta vaihtoehdosta

export default {
    data() {
        return {
            role: ''
        }
    }
}
<input type="radio" value="frontend-dev" v-model="role" /> Frontend developer
<input type="radio" value="backend-dev" v-model="role" /> Backend developer
<input type="radio" value="fullstack-dev" v-model="role" /> Fullstack developer

Luupataan arvoja

Eo. roolit on nyt datana

export default {
    data() {
        return {
            role: '',
            roleOptions: [
                { id: 'frontend-dev', name: 'Frontend developer'},
                { id: 'backend-dev', name: 'Backend developer'},
                { id: 'fullstack-dev', name: 'Fullstack developer'}
            ]
        }
    }
}

Luuppaaminen tapahtuu v-for -attribuutilla.

<div v-for="option in roleOptions">
    <input type="radio" :value="option.id" v-model="role" /> {{ option.name }}
</div>

Nyt jokaiselle roolille roleOptions -taulukossa muodostuu oma div -elementti. Huomaa että inputin arvo on määritelty :value -attribuutilla. Kaksoispiste attribuutin edessä tarkoittaa, että lainausmerkeissä annettu arvo evaluoidaan. Näin arvot ovat "frontend-dev", "backend-dev" ja "fullstack-dev". Ilman kaksoispistettä kaikkien arvo olisi "option.id".

Jos tarvitsee käyttää indeksiä luupatessa, sen saa mukaan näin

<div v-for="(item, index) in array">
</div>

Myös objektin kenttiä voi luupata

<div v-for="value in object"></div>
<div v-for="(value, key) in object"></div>

Checkbox

Tehdään true/false checkbox, jolla valitaan halutaanko tilata uutiskirje sekä lista checkboxeja, joilla valitaan teknologioita

export default {
    data() {
        return {
            subscribe: false,
            technologies: [],

            techOptions: [
                { id: 'js', name: 'JavaScript' },
                { id: 'ts', name: 'TypeScript' },
                { id: 'vue', name: 'Vue.js' },
                { id: 'react', name: 'React' },
                { id: 'angular', name: 'Angular' },
                { id: 'java', name: 'Java' },
                { id: 'dotnet', name: '.NET' },
                { id: 'python', name: 'Python' }
            ],
        }
    }
}

True/false tapauksessa v-model riittää

<input type="checkbox" v-model="subscribe" />

Kun checkboxeilla valitaan useampi arvo, voidaan käyttää samanlaista rakennetta kuin aiemmin roolissa. Tällä kertaa datassa kenttä on vain taulukko.

<div v-for="option in techOptions">
    <input type="checkbox" :value="option.id" v-model="technologies" /> {{ option.name }}
</div>

Select

export default {
    data() {
        return {
            country: '',
            languages: [],

            countryOptions: [
                'Finland',
                'Sweden',
                'Norway',
                'United States'
            ],
            languageOptions: [
                { code: 'fi', label: 'Finnish'},
                { code: 'sv', label: 'Swedish'},
                { code: 'en', label: 'English'}
            ];
        }
    }
}
<select v-model="country">
  <option value="">Choose</option>
  <option v-for="option in countryOptions" :value="option">{{ option }}</option>
</select>

<select v-model="languages" multiple>
  <option v-for="option in languageOptions" :value="option.code">{{ option.label }}</option>
</select>

Ehdollinen renderöinti

Jos elementti halutaan näyttää vain ehdon täyttyessä voi käyttää v-if-, v-else-if- ja v-else -attribuutteja. Esim. näytetään eo. teknologialista vain, jos rooli on valittu. Muussa tapauksessa näytetään infoteksti.

<div v-if="role">
    <div v-for="option in techOptions">
        <input type="checkbox" :value="option.id" v-model="technologies" /> {{ option.name }}
    </div>
</div>
<span v-else>Select role first</span>

Eventit

Elementtien tapahtumia voi kuunnella lisäämällä eventin eteen @ -merkin.

<button @click="save">Save</button>
<button @click="cancel(true)">Cancel</button>

Metodit laitetaan omaan objektiinsa methods

export default {
    data() {
        return {
            name: ''
        }
    },
    methods: {
        save() {
            alert(this.name);
        },
        cancel(goBack) {
            // ...
        }
    }
}

Lasketut arvot

Jos jokin arvo pitää johtaa muiden arvojen perusteella, voi käyttää laskettuja arvoja (computed). Ne ovat kuten metodit, mutta niiden arvo pidetään välimuistissa ja lasketaan uudestaan vain lähtöarvojen muuttuessa. Esimerkiksi muutetaan aiemmin käydyt rooli ja teknologiat sellaisiksi, että näytetään vain rooliin liittyvät teknologiat.

export default {
    data() {
        return {
            role: '',
            technologies: [],

            techOptions: [
                { id: 'js', name: 'JavaScript', roles: ['frontend-dev','fullstack-dev']},
                { id: 'ts', name: 'TypeScript', roles: ['frontend-dev','fullstack-dev']},
                { id: 'vue', name: 'Vue.js', roles: ['frontend-dev','fullstack-dev']},
                { id: 'react', name: 'React', roles: ['frontend-dev','fullstack-dev']},
                { id: 'angular', name: 'Angular', roles: ['frontend-dev','fullstack-dev']},
                { id: 'java', name: 'Java', roles: ['backend-dev','fullstack-dev']},
                { id: 'dotnet', name: '.NET', roles: ['backend-dev','fullstack-dev']},
                { id: 'python', name: 'Python', roles: ['backend-dev','fullstack-dev']}
            ],
        }
    },
    computed: {
        roleTechOptions(){
            if(this.role){
                return this.techOptions.filter(t => t.roles.includes(this.role));
            }
            return [];
        }
    }
}

Templatessa ei tarvitse muuta kuin osoittaa tähän laskettuun arvoon

<div v-for="option in roleTechOptions">
    <input type="checkbox" :value="option.id" v-model="technologies" /> {{ option.name }}
</div>

Datan muutoksiin reagointi

Jos datan muuttuessa tarvitsee tehdä jotain voi käyttää watch -metodeita. Esimerkiksi roolin vaihtuessa voi tyhjentää valitut teknologiat. Watch-objektiin laitetaan samanniminen metodi, kuin tarkkailtava arvo.

export default {
    data() {
        return {
            role: '',
            technologies: [],

            techOptions: [/* ... */],
        }
    },
    watch: {
        role() {
            this.technologies = [];
        }
    }
}

Komponentin elinkaari

Komponentin elinkaaressa on useita tapahtumia, joihin voi tarttua. Esim. haetaan dataa ajaxilla, kun komponentti on luotu

import api from './api'
export default {
    data() {
        return {
            role: '',
            technologies: [],
            techOptions: []
        }
    },
    created(){
        // haetaan ajaxilla dataa
        api.getTechnologies().then(data => {
            this.techOptions = data;
        });
    }
}