Jednostránkové aplikace s Vue.js a Flask:Nastavení Vue.js

Nastavení a seznámení s Vue.js

Úvod

Toto je úvodní příspěvek k sérii výukových programů o používání Vue.js a Flask pro vývoj webu v plném rozsahu. V této sérii ukážu, jak vytvořit webovou aplikaci pro průzkum, kde architektura aplikace sestává z front-endu složeného z Vue.js Single Page Application (SPA) a backendového REST API pomocí webového rámce Flask.

Tento první příspěvek se bude zabývat základním nastavením a strukturou projektu pomocí směrnice Vue.js v-for a fází životního cyklu komponent.

Obsah seriálu

  1. Nastavení a seznámení s Vue.js (jste zde)
  2. Navigace Vue Router
  3. Správa státu se společností Vuex
  4. RESTful API s Flask
  5. Integrace AJAX s REST API
  6. Ověření JWT
  7. Nasazení na virtuální privátní server

Nastavení rozhraní s vue-cli a webpack

Budu používat dva velmi důležité nástroje pro projekt Vue.js, kterými jsou oficiální rozhraní příkazového řádku Vue.js (CLI) a velmi výkonný balík modulů a webový balíček nástrojů pro sestavení. Oba tyto nástroje spoléhají na runtime Node.js a jeho správce balíčků, npm. Pokud jste uzel ještě nenainstalovali, prostudujte si prosím instalační dokumentaci Node.js pro váš systém, která bude také obsahovat instalaci npm.

Nainstalujte Vue.js CL (vue-cli):

$ npm install vue-cli -g

Nyní s nainstalovaným CLI jej použiji k inicializaci aplikace Vue.js SPA. CLI provádí následující:

  1. Nainstalujte a nakonfigurujte webový balíček pro seskupení mého kódu
  2. Nainstalujte vývojový server s hot-reload (server se automaticky restartuje při změně souboru)
  3. Přidat závislost pro vue-router
  4. Vybudujte základní strukturu souborů Vue.js SPA

Nejprve vytvořím složku na vysoké úrovni, která bude obsahovat veškerý kód pro tento tutoriál s názvem „průzkum“. Dále vytvořím další dva adresáře nazvané „frontend“ (pro Vue.js SPA) a „backend“ (pro vývoj REST API), poté změním svůj pracovní adresář na adresář frontendu.

$ mkdir survey
$ cd survey
$ mkdir frontend
$ mkdir backend
$ cd frontend

A teď to pravé kouzlo. Je zadán inicializační příkaz Vue CLI, který mě poté vyzve k zodpovězení řady otázek.

Stisknutím klávesy Enter přijmete výchozí hodnoty pro otázky (i) Název projektu, (ii) Popis projektu, (iii) Autor projektu, (iv) Samostatné sestavení. Když budete vyzváni k instalaci vue-routeru, zadejte "Y" pro ano. Zadejte "n" pro zbývající položky a přijměte výchozí hodnoty.

$ vue init webpack survey-spa

? Project name survey-spa
? Project description A Vue.js project
? Author Adam McQuistan <[email protected]>
? Vue build standalone
? Install vue-router? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) npm

   vue-cli · Generated "survey-spa".


# Installing project dependencies ...
...

Nyní by měl existovat nový adresář s názvem „survey-spa“. Změňte adresáře do tohoto adresáře a zadejte příkaz npm ke kompilaci projektu a spuštění dev serveru.

$ cd survey-spa
$ npm run dev

Nyní mohu do okna prohlížeče zadat http://localhost:8080 a měla by se mi zobrazit stránka šablony Vue.js podobná té, která je zobrazena níže.

Struktura souborů, která byla vytvořena, vypadá jako níže. Záměrně jsem vynechal bažiny nesmyslů ve složce node_modules.

survey-spa/
├── README.md
├── build
│   ├── build.js
│   ├── check-versions.js
│   ├── logo.png
│   ├── utils.js
│   ├── vue-loader.conf.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config
│   ├── dev.env.js
│   ├── index.js
│   └── prod.env.js
├── index.html
├── package-lock.json
├── package.json
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   └── HelloWorld.vue
│   ├── main.js
│   └── router
│       └── index.js
└── static

Při prvních několika pokusech se to zdá být poněkud ohromující, ale nebojte se, že se opravdu musíme zabývat pouze soubory v adresáři src/ a souborem index.html. Ostatní soubory jsou samozřejmě důležité a možná se jednoho dne dostanu k tomu, k čemu se používají, ale zatím je prostě ignorujte.

Soubory v adresáři src/ jsou místo, kde budu psát kód pro řízení funkčnosti aplikace. Pojďme tyto soubory otevřít a získat představu o tom, co se děje.

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>survey-spa</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

Toto je jediný soubor HTML, který Vue SPA využívá, a zřídka obsahuje mnohem více, než je uvedeno výše, s výjimkou toho, že někdy v tomto souboru vytvoříte odkazy na frameworky CSS a další knihovny JavaScriptu. Jediný div prvek, který je vytvořen s výchozím id "app" je to, k čemu se připojí hlavní instance Vue. Tento objekt Vue vloží HTML a CSS, které jsou v komponentách, o kterých bude řeč později, do div k vytvoření uživatelského rozhraní.

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

Soubor main.js je primárním vstupním bodem pro aplikaci a je místem, kde zaregistrujete instanci Vue a rozšíření, jako je vue-router a vuex. Jak vidíte, zde sídlí instance Vue. Instance je registrována v aplikaci div diskutované výše, navíc je napájen objektem routeru a vysokoúrovňovým App komponenta.

App.vue

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Soubor App.vue slouží jako součásti aplikace nejvyšší úrovně a často obsahuje obecné rozvržení aplikace. Komponenty Vue mají specifickou strukturu obsahující <template> sekce pro HTML specifické pro komponenty, <script> k definování Vue objekt a chování této komponenty implementované v JavaScriptu a <styles> sekce pro pravidla CSS / SCSS. Tento poslední kousek však může být trochu matoucí, protože ve výchozím nastavení se pravidla stylu, která definujete v komponentě, nevztahují pouze na tuto komponentu. Ve skutečnosti ovlivňují všechny prvky v celém projektu, pokud nepřidáte scoped atribut k <style> prvek.

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

Skript index.js v adresáři směrovače je místem, kde jsou definovány adresy URL pro aplikaci a mapovány na komponenty. První dva řádky importují Vue a Router objekty, které jsou poté propojeny pomocí use metoda na Vue objekt.

Výchozí trasa, která je poskytnuta ze šablony webového balíčku vue-cli, je jednoduše kořenová nebo indexová trasa pro aplikaci, která serveruje až HelloWorld komponent. Chcete-li namapovat cestu trasy ke komponentě, musí být nejprve importována a poté musíte definovat objekt trasy v routes pole, které mu dá cestu, název a komponentu, která se má zobrazit.

komponenty/HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li>
        <a href="https://vuejs.org" target="_blank">Core Docs</a>
      </li>
      <li>
        <a href="https://forum.vuejs.org" target="_blank">Forum</a>
      </li>
      <li>
        <a href="https://chat.vuejs.org" target="_blank">Community Chat</a>
      </li>
      <li>
        <a href="https://twitter.com/vuejs" target="_blank">Twitter</a>
      </li>
      <br>
      <li>
        <a href="http://vuejs-templates.github.io/webpack/" target="_blank">
          Docs for This Template
        </a>
      </li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li>
        <a href="http://router.vuejs.org/" target="_blank">vue-router</a>
      </li>
      <li>
        <a href="http://vuex.vuejs.org/" target="_blank">vuex</a>
      </li>
      <li>
        <a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a>
      </li>
      <li>
        <a href="https://github.com/vuejs/awesome-vue" target="_blank">
          awesome-vue
        </a>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

V adresáři "components" jsou umístěny komponenty uživatelského rozhraní. HelloWorld komponenta výše opět obsahuje tři základní sekce šablonu, skript a styl, které všechny mají nějaký příklad obsahu z inicializační šablony vue-cli.

Podívejte se na obsah sekce skriptů. Zde uvidíte, že se objekt exportuje. Tento objekt bude vložen do Vue instance, která byla inicializována v souboru main.js. Uvnitř tohoto objektu JavaScript je data metoda, která vrací objekt. Tento objekt je místo, kam můžete umístit stav na úrovni komponenty (data) a v tomto příkladu je to jediná vlastnost nazvaná msg .

Stav komponenty můžete zobrazit a zobrazit podle názvu vlastnosti v HTML v sekci šablony. V uvedeném příkladu to vidíte jako {{ msg }} . Dvojité složené závorky jsou výchozí syntaxí šablony pro provádění interpolace textu a jsou inspirovány systémem šablon Moustache. Kdykoli chcete zobrazit data v HTML vaší komponenty, zabalte je do dvojitých složených závorek.

Přinést nějaký styl

Aby tato aplikace byla o něco lepší, budu používat rámec Bulma CSS. Cílem tohoto tutoriálu nebude, jak používat Bulmu, ale přesto ji chci zahrnout, abych odvrátil fádní vzhled nestylovaného HTML.

Zdarma e-kniha:Git Essentials

Prohlédněte si našeho praktického průvodce učením Git s osvědčenými postupy, průmyslově uznávanými standardy a přiloženým cheat sheetem. Přestaňte používat příkazy Google Git a skutečně se naučte to!

Zpět v terminálu ve stejném adresáři jako soubor package.json nainstalujte a uložte bulmu do projektu pomocí následujícího příkazu:

$ npm install --save bulma

Kromě toho si budu muset nainstalovat nějaké dev nástroje, abych správně načetl styly pro aplikaci, aby komponenty věděly, jak s nimi pracovat. Chcete-li to provést, npm nainstalujte tyto dodatečné balíčky.

$ npm install --save-dev vue-style-loader
$ npm install --save-dev css-loader
$ npm install --save-dev sass-loader
$ npm install --save-dev node-sass

Nyní otevřete App.vue a nahraďte sekci stylu tím, co je níže, čímž se importuje rámec bulma pomocí syntaxe importu scss.

<style lang="scss">
@import '~bulma/bulma'
</style>

Přidejte domovskou stránku (stránku)

Dobře, teď, když máme základní znalosti o struktuře a hlavních částech aplikace Vue.js SPA, mohu začít psát kód.

Začněte přejmenováním souboru HelloWorld.vue na Home.vue a poté vymažte obsah částí šablony, skriptu a stylu. V App.vue také odstraňte řádek pro logo obrázku Vue <img src="./assets/logo.png"> a vymažte obsah <style> prvek, když jste tam. Nakonec otevřete router/index.js a importujte komponentu Home.vue místo HelloWorld.vue a aktualizujte objekt trasy, aby používal komponentu Home.

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }
  ]
})

Nyní otevřete soubor Home.vue a vyplňte sekci skriptu tím, co je níže.

export default {
  data() {
    return {
      surveys: [{
      id: 1,
      name: 'Dogs',
      created_at: new Date(2017, 12, 1),
      questions: [
        {
          id: 1,
          text: 'What is your favorite dog?',
          choices: [
            { id: 1, text: 'Beagle', selected: 0 },
            { id: 2, text: 'Labrador', selected: 0 },
            { id: 3, text: 'Rottweiler', selected: 0 }]
        }, {
          id: 2,
          text: 'What is your second favorite dog?',
          choices: [
            { id: 5, text: 'Beagle', selected: 0 },
            { id: 6, text: 'Labrador', selected: 0 },
            { id: 7, text: 'Rottweiler', selected: 0 }]
        }]
      }, {
        id: 2,
        name: 'Cars',
        created_at: new Date(2017, 12, 3),
        questions: [
          {
            id: 5,
            text: 'What is your favorite car?',
            choices: [
              { id: 17, text: 'Corvette', selected: 0 },
              { id: 18, text: 'Mustang', selected: 0 },
              { id: 19, text: 'Camaro', selected: 0 }]
          }, {
            id: 6,
            text: 'What is your second favorite car?',
            choices: [
              { id: 21, text: 'Corvette', selected: 0 },
              { id: 22, text: 'Mustang', selected: 0 },
              { id: 23, text: 'Camaro', selected: 0 }]
          }]
      }]
    }
  }
}

To nám dává nějaká falešná data, se kterými můžeme pracovat. Jak jistě víte, představuje dva průzkumy, jeden o psech a druhý o autech. Data poskytnou hnací sílu HTML, který se chystáme napsat, poskytnutím obsahu k zobrazení.

Nyní do sekce šablon přidám div která zabalí všechny mé ostatní prvky. Každá komponenta Vue musí mít jeden nadřazený prvek, nesmí existovat sourozenecké prvky nejvyšší úrovně nebo se komponenta nezkompiluje. Uvnitř tohoto divu přidám sekci pro hlavičku hrdiny Bulma.

Pod záhlavím bude další sekce pro zobrazení názvu každého průzkumu a data jeho vytvoření. Právě v tomto bloku HTML začneme vidět některé úžasné věci, které poskytuje Vue.js.

<template>
<div>
  <section class="hero is-primary">
    <div class="hero-body">
      <div class="container has-text-centered">
        <h2 class="title">Check out recent surveys</h2>
      </div>
    </div>
  </section>
  <section class="section">
    <div class="container">
      <div class="card" v-for="survey in surveys" v-bind:key="survey.id">
        <div class="card-content">
          <p class="title">{{ survey.name}}</p>
          <p class='subtitle'>{{ survey.created_at.toDateString() }}</p>
        </div>
      </div>
    </div>
  </section>
</div>
</template>

Uložte všechny neuložené soubory v projektu a obnovte svůj prohlížeč, který by nyní měl vypadat následovně:

Jak můžete vidět na snímku obrazovky, zobrazují se dvě karty průzkumu Bulma. Tyto dva průzkumy mapují pole objektů průzkumu, které byly v mé datové funkci mého Home komponentu, kterou jsem vložil do svého HTML pomocí direktivy v-for.

Podívejte se znovu na níže uvedenou podsekci původního kódu šablony, která představuje průzkum. Celý tento prvek a jeho potomci se opakují jednou pro každý průzkum v surveys pole. V podstatě data řídí generování HTML.

Část v-bind:key přidává atribut s názvem key rovná se id průzkumu ke každému div s "kartou" třídy. Vue používá tyto klíče k explicitnímu sledování každého vytvářeného uzlu v DOM, což pomáhá při vedení účetnictví a výkonu. Doporučuje se vždy nastavit jedinečný klíč pro nejvzdálenější prvek, který se používá ve spojení s direktivou v-for.

<div class="card" v-for="survey in surveys" v-bind:key="survey.id">
    <div class="card-content">
      <p class="title">{{ survey.name}}</p>
      <p class='subtitle'>{{survey.created_at.toDateString()}}</p>
    </div>
</div>

Direktiva v-for používá syntaxi item in items kde items je iterovatelný, jako je pole nebo vlastnosti objektu a item je alias pro každý prvek v iterovatelné. Existují však varianty této syntaxe, které umožňují větší flexibilitu a kontrolu.

Řekněme například, že jsem měl pole písmen var letters = ['a', 'd', 'a', 'm'] který jsem chtěl použít k vytvoření pravidelného ole HTML neuspořádaného seznamu, který zobrazuje každé písmeno a jeho odpovídající index. To by se dalo udělat s touto variantou v-for:

  <ul>
    <li v-for="(letter, i) in letters" v-bind:key="i">
      Index position {{ i }} has letter {{ letter }}
    </li>
  </ul>

Výsledkem je následující výstup:

• Index position 0 has letter a
• Index position 1 has letter d
• Index position 2 has letter a
• Index position 3 has letter m

Pro iteraci vlastností objektu je syntaxe velmi podobná. Daný objekt jako var person = { name: 'adam', occupation: 'software developer', residence: 'lincoln, nebraska' } , iterace s direktivou v-for by vypadala takto:

  <ul>
    <li v-for="(value, key) in person" v-bind:key=”key”>
      key -> {{ key }}, value -> {{ value }}
    </li>
  </ul>
• key -> name, value -> adam
• key -> occupation, value -> software developer
• key -> residence, value -> lincoln, nebraska

Zesměšňování požadavku AJAX na průzkumy

Mám svou první funkční komponentu uživatelského rozhraní zobrazující kolekci průzkumů, ale nakonec bude muset skutečná aplikace načíst data průzkumu z našeho REST API. Aby to bylo trochu realističtější, rád bych zesměšnil funkce pro požadavek AJAX na podávání Home dílčí průzkumy.

V adresáři src vytvořte novou složku s názvem „api“ a poté do ní přidejte skript s názvem index.js. To je místo, kde budu zesměšňovat své funkce AJAX. Do tohoto nového souboru vyjměte a vložte surveys pole z komponenty Home.vue jako globální konstanta.

// api/index.js

const surveys = [{
  id: 1,
  name: 'Dogs',
  created_at: new Date(2018, 1, 1),
  questions: [{
    id: 1,
    text: 'What is your favorite dog?',
    choices: [
      { id: 1, text: 'Beagle', selected: 0 },
      { id: 2, text: 'Labrador', selected: 0 },
      { id: 3, text: 'Rottweiler', selected: 0 }]
  }, {
    id: 2,
    text: 'What is your second favorite dog?',
    choices: [
      { id: 5, text: 'Beagle', selected: 0 },
      { id: 6, text: 'Labrador', selected: 0 },
      { id: 7, text: 'Rottweiler', selected: 0 }]
  }]
}, {
  id: 2,
  name: 'Cars',
  created_at: new Date(2018, 1, 3),
  questions: [{
    id: 5,
    text: 'What is your favorite car?',
    choices: [
      { id: 17, text: 'Corvette', selected: 0 },
      { id: 18, text: 'Mustang', selected: 0 },
      { id: 19, text: 'Camaro', selected: 0 }]
  }, {
    id: 6,
    text: 'What is your second favorite car?',
    choices: [
      { id: 21, text: 'Corvette', selected: 0 },
      { id: 22, text: 'Mustang', selected: 0 },
      { id: 23, text: 'Camaro', selected: 0 }]
  }]
}]

Pod tímto polem průzkumů vytvořte funkci nazvanou fetchSurveys který po 300 milisekundách vrátí příslib s polem průzkumů (pro simulaci zpoždění API). Funkci bude nutné exportovat, aby k ní bylo možné přistupovat z Home komponenta.

export function fetchSurveys() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(surveys)
    }, 300)
  })
}

Zpět v datové funkci Home komponenta inicializovat surveys vlastnost do prázdného pole a importujte fetchSurveys funkce v sekci skriptů.

<script>
import { fetchSurvey } from '@/api'
export default {
 data() {
    return {
      surveys: []
    }
  }
}
</script>

Komponenty Vue mají řadu definovaných fází životního cyklu, které jsou pro vývojáře smysluplné, když dělají různé věci, jako je stahování dat pomocí požadavku AJAX. Aby bylo možné vložit data z průzkumu do Home komponentu, kterou budu muset zapojit do jedné z fází životního cyklu Vue, konkrétně do beforeMount etapa. Existuje několik dalších fází, které jsou užitečné pro mnohem více věcí než jen požadavky AJAX, ale podrobné vysvětlení odkládám v oficiální dokumentaci Vue.js.

beforeMount fáze životního cyklu funguje dobře pro volání API, protože se provádí těsně před zahájením montáže naší komponenty a těsně před render je volána na naší komponentě. To poskytuje čas na načtení dat před zobrazením uživateli.

Chcete-li využít výhod beforeMount fázi Home komponenta vše, co musím udělat, je přidat ji jako novou metodu do objektu Vue komponenty. Uvnitř této funkce zavolám na můj fetchSurveys a přiřadit vrácené průzkumy průzkumům data vlastnost.

<script>
import { fetchSurveys } from '@/api'
export default {
  data() {
    return {
      surveys: []
    }
  },
  beforeMount() {
    fetchSurveys().then(response => {
      this.surveys = response
    })
  }
}
</script>

Uložením všech souborů v projektu a obnovením prohlížeče nyní získám stejnou domovskou stránku, jakou jsme viděli dříve, ale nyní se simulovaným voláním AJAX.

Zdroje

Chcete se dozvědět více o Vue.js a vytváření front-end webových aplikací? Zkuste se podívat na některé z následujících zdrojů, abyste se mohli hlouběji ponořit do tohoto rozhraní front-end:

  • Vue.js 2 – Kompletní průvodce
  • Vývojářský kurz Ultimate Vue JS 2

Závěr

Tento příspěvek pokrývá základy nastavení aplikace Vue.js SPA s vue-cli pomocí šablony webpack. Kromě nastavení projektu jsem se zabýval tím, jak používat data ve formě iterable k dynamickému generování obsahu uživatelského rozhraní pomocí výkonné direktivy v-for Vue.js. V posledním hlavním tématu jsem se zaměřil na fáze životního cyklu komponent a na způsob beforeMount fáze může být užitečná při načítání dat do komponenty pomocí falešného požadavku AJAX.

Příští příspěvek se budu zabývat tím, jak používat rozšíření vue-router k toku z jedné stránky na druhou, což dává naší aplikaci koncept pracovního postupu. Kód pro tento tutoriál najdete na mém účtu GitHub, který obsahuje větev pro každý příspěvek. Děkujeme za přečtení a prosím, neváhejte se vyjádřit nebo kritizovat níže.