Vikky avatar

Виктор Шостак
   

Как построить простое SPA (Single Page Application) приложение на Vue.js 2.x?


TL;DR

Эта статья поможет вам понять:

  • Базовые принципы построения SPA приложений на Vue.js;
  • Как быстро создавать каркас Vue-приложения через консоль (Vue CLI);
  • Логику Vue-компонентов и как их использовать (Vue Components);
  • Как подключаться к стороннему API и использовать полученные данные.

Предисловие

Хочу поделиться с вами своим авторским переводом (с переработкой и актуализацией информации на 1 июня 2017) статьи «How To Build A Simple Single Page Application Using Vue 2» от Ogundipe Samuel Ayo, которая была размещена 15 марта 2017 года, но почему-то прошла мимо (меня) на Scotch.io.

Что было «переработано» из оригинала?

В последних версиях vue-cli можно сразу же генерировать приложение с vue-router, поэтому этот раздел был значительно сокращён. Вырезана никому не нужная «вода». Оригинал разделён на две части, но, для вашего удобства, я объединил всё в одну статью.

Комментарии и дельные замечания — приветствуются. Приятного чтения!

Часть 1. Что мы будем строить?

Сегодня мы научимся построению одностраничного приложения (Single Page Application, SPA) с использованием прогрессивного JavaScript-фреймворка Vue.js версии 2.x (актуальная, на момент написания, 2.3.3).

Vue (произносится /vjuː/, примерно как view) — это прогрессивный фреймворк для создания пользовательских интерфейсов. В отличие от фреймворков-монолитов, Vue создан пригодным для постепенного внедрения.

Его ядро в первую очередь решает задачи уровня представления (view), что упрощает интеграцию с другими библиотеками и существующими проектами.

С другой стороны, Vue полностью подходит и для создания сложных одностраничных приложений (SPA, Single-Page Applications), если использовать его совместно с современными инструментами и дополнительными библиотеками.

Источник: https://ru.vuejs.org/v2/guide/

Что такое SPA приложение и зачем?

SPA — это не просто сайт, а полноценное приложение, работа которого полностью перенесена на сторону клиента, то есть в браузер. И в отличие от обычных сайтов, SPA предоставляет не просто контент, а полноценный сервис, общаясь с сервером только чистыми данными.

Философия и главное предназначение данной парадигмы, на мой взгляд, это потеснить мобильный рынок нативных приложений и предложить более универсальный подход к UX. Уходят времена, когда требовалась разработка и сайта и мобильного приложения. Благодаря таким фреймворкам, как Vue.js, теперь можно делать проекты «2 в 1».

А ещё, один раз загрузившись в кэш браузера, такое приложение будет работать невероятно быстро! Ведь всё уже будет на вашем устройстве, а с сервера будут приходить лишь голые данные.

Всё начинается с консоли

Для автоматизации рутины по настройке конфигурации проекта, разработчик Vue.js — Эван Йю (Evan You) — сделал отличный инструмент: vue-cli. Это интерфейс командной строки (Command Line Interface, CLI) для быстрого старта проекта без головной боли и поисков необходимых пакетов.

Я буду приводить все консольные команды для *nix подобных ОС (Linux/Mac), которые могут отличаться от Windows. Для комфортной разработки под ОС от Microsoft — настоятельно рекомендую обновиться до последней версии Windows 10 Creators Update, где вшит полноценный Bash/WSL с Ubuntu 16.04 прямо в систему.

Установка такая же простая, как и использование:

$ sudo npm i -g vue-cli

Вот и всё, мы готовы создать наше первое SPA приложение по шаблону. Кстати, я люблю Webpack 2, так что сторонники Browserify не обессудьте :)

$ vue init webpack spa-project

? Project name spa-project
? Project description A Vue.js project
? Author Vikky Shostak <my-mail@gmail.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? Yes
? Setup e2e tests with Nightwatch? No

   vue-cli · Generated "spa-project".

После этого переходим в папку с проектом cd spa-project, устанавливаем зависимости npm i и можем протестировать работу dev-сервера командой npm run dev.

Откроется новое окно браузера с адресом http://localhost:8080/#/. Если вы увидели страницу «Welcome to Your Vue.js App», то всё работает! Продолжаем погружение.

Удобная работа с Vue в браузере

Ещё один инструмент, который экономит время при отладке приложения на Vue.js в браузере — это Vue Devtools. Поставляется, как плагин к браузеру Google Chrome.

spa-vuejs-devtools

Разбираемся с vue-router

Если вы обратите внимание на адресную строку, то заметили, что в конец прибавился хэш #/. Даже когда мы его стираем, то он всё равно его настырно прописывает. Избавимся от этого хэша, чтобы поисковые роботы сказали нам спасибо.

Файл ./spa-project/src/router/index.js:

// Импорт необходимых пакетов (спасибо vue-cli за это!)
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'

Vue.use(Router) // говорим Vue использовать vue-router

export default new Router({
  // все пути будем прописывать тут
  routes: [
    { path: '/', name: 'Hello', component: Hello } // главная страница
  ],
  mode: 'history' // <-- добавляем эту строку
})

Проверяем. Теперь все URL нашего приложения будут строиться от корня /.

Добавляем новый путь (route)

Пришло время добавить страницу «О себе» (да, вот так всё непредсказуемо). В папке ./spa-project/src/components создаём файл About.vue со следующим содержанием:

<!-- шаблон компонента -->
<template>
  <div class="about">
    <h1>{{ msg }}</h1>
  </div>
</template>

<!-- подключение логики этого компонента -->
<script>
export default {
  name: 'about',
  data () {
    return {
      msg: 'Страница «О себе» (About.vue)' // переменная, которая будет передана в шаблон
    }
  }
}
</script>

<!-- подключение стилей, только для этого компонента -->
<style scoped>
h1, h2 {
  font-weight: normal;
}

a {
  color: #42b983;
}
</style>

Отлично. Теперь дадим Vue.js понять, где искать эту страницу. Редактируем файл ./spa-project/src/router/index.js:

// ...
import Hello from '@/components/About'

// ...

export default new Router({
  routes: [
    // ...
    { path: '/about', name: 'About', component: About } // страница «О себе»
  ],
  // ...
})

Перейдём же, скорей, по адресу http://localhost:8080/about, чтобы проверить результат своей работы!

Регистрируем новый путь

Согласитесь, неудобно переходить по сайту, редактируя URL в адресной строке браузера. Упростим задачу с помощью <router-link> (более полное описание возможностей построения ссылок — читайте тут). Добавляем в шаблон About.vue эту строку:

<template>
  <div class="about">
    <!-- ... -->
    <router-link :to="{ path: '/' }">Главная</router-link>
  </div>
</template>

<!-- ... -->

Аналогичным образом поступим и с главной страницей Hello.vue.

spa-vuejs-about-page-3

Усложним задачу. Динамическая загрузка контента со стороннего API

Для работы с HTTP запросами (GET, POST и так далее), я использую библиотеку axios. Устанавливаем её через npm i axios. Далее, создадим новый компонент User.vue и поместим в него следующее:

<template>
  <div class="user">
    <h1>{{ msg }}</h1>

    <!-- выведем имя, логин и ID загруженного пользователя  -->
    <h2>{{ user[0].name }} @{{ user[0].username }} (ID {{ user[0].id }})</h2>

    <router-link :to="{ path: '/' }">Главная</router-link>
    <router-link :to="{ path: '/about' }">О себе</router-link>
  </div>
</template>

<script>
import axios from 'axios' // импортируем библиотеку axios

export default {
  name: 'user',
  props: ['id'], // следим за параметром id из URL
  data () {
    return {
      msg: 'Страница пользователя (User.vue)',
      user: [] // создаём пустой массив
    }
  },
  methods: {
    getUserByID: function(id) {
      const api_url = 'https://jsonplaceholder.typicode.com/users/' // используем JSON заглушку

      // делаем GET запрос
      axios.get(api_url + id) 
      .then((response) => {
        this.user.push(response.data); // пишем ответ в массив user
      })
      .catch((error) => {
        console.log(error); // выводим ошибку в консоль , если что-то пошло не так
      });
    }
  },
  mounted() {
    this.getUserByID(this.id) // вызываем наш метод с параметром id из URL
  }
}
</script>

<style scoped>
h1, h2 {
  font-weight: normal;
}

a {
  color: #42b983;
}
</style>

Как и раньше, подключаем этот компонент в роутере, но с дополнительным параметром :id и флагом props: true:

// ...
import User from '@/components/User'

// ...

export default new Router({
  routes: [
    // ...
    { path: '/user/:id', name: 'User', component: User, props: true } // страница пользователя
  ],
  // ...
})

Теперь, если мы перейдём по адресу /user/2, то результат будет примерно такой:

spa-vuejs-about-page-2

Хорошо, это я понял(а). Что делать дальше?

Отличный вопрос, на который я с радостью отвечу: вникать в документацию Vue.js (есть на русском) и практиковаться в создании более сложных SPA приложений.

И, да, не бойтесь спрашивать (не только тут) совета!