Может войдёшь?
Черновики Написать статью Профиль

Учимся использовать Vue-router в одностраничных приложениях

перевод

Одна из моих любимых вещей в Vue.js — он работает на простейших страницах с простейшими компонентами. Вам не нужны никакие сложные инструменты сборки или деревья зависимостей.

Но Vue не ограничивается только простыми компонентами. Vue-resource делает AJAX простым, с vue-router можно настроить маршрутизацию одностраничного приложения почти без усилий. И я обещаю, когда-нибудь я выучу и Vuex.

Я хочу показать вам, насколько просто использовать vue-router для создания одностраничного приложения с помощью Vue. И уж поверьте мне — это просто. Если вы уже создавали свой компонент с помощью Vue, то 90% работы позади.

Настройка

Как это часто бывает, в качестве инструмента для сборки я выбрал Laravel Elixir.

Вы можете использовать любую систему сборки, которая предоставляет вам доступ к вашим NPM-пакетам. Или вы можете включить пакет в сборку вручную (с помощью CDN ) или с помощью Bower. В итоге вам нужен vue-router, установленный любым способом. Если вы не собираетесь использовать Elixir, то просто пропустите следующий раздел.

Установка Vue и vue-router с помощью Laravel Elixir (не обязательно)

Если вы собираетесь начать новый проект используя Laravel Elixir, прочтите документацию с инструкциями по базовой установке. Затем добавьте vue и vue-router:

shnpm install vue vue-router --save

Далее вам надо добавить задачу Browserify для вашего JavaScript файла:

js// gulpfile.js
elixir(function (mix) {
  mix.browserify('app.js');
});

Теперь ожидается, что у вас есть файл resources/assets/js/app.js, который будет передаваться через Browserify и Babel и выводиться в public/js/app.js. Создайте «ресурсную» версию этого файла и выполните shgulp watch, чтобы запустить его.

Включение зависимостей

Вам надо включить Vue и vue-router в свой основной JavaScript файл с помощью любой доступной вам системы импорта:

jsvar Vue = require('vue');
var VueRouter = require('vue-router');

Vue.use(VueRouter);

Мы включили Vue и vue-router, и затем связывали их друг с другом. Теперь давайте напишем наше приложение.

Создание своего приложения

Как в любом Vue-приложении, нам надо создать базовое приложение. Но в отличие от других Vue-приложений, ядро шаблонной работы, которую мы будем делать, это отображение нескольких компонентов по нескольким маршрутам. Во Vue нет такого нового понятия как «страница», каждая страница — это просто компонент, который может содержать другие компоненты.

Давайте создадим наше приложение и наш маршрутизатор:

jsvar App = Vue.extend({});

var router = new VueRouter();

router.start(App, '#app');

Вот и всё! Оно не будет ничего делать, потому что мы не отобразили ни одного маршрута, но мы определили приложение, определили маршрутизатор, собрали их воедино, и затем инициализировали маршрутизатор.

Отображение компонентов по маршрутам

У нас есть приложение и маршрутизатор, давайте определим несколько маршрутов:

jsvar App = Vue.extend({});

var router = new VueRouter();

var Home = Vue.extend({
  template: 'Добро пожаловать на <b>главную страницу</b>!'
});

var People = Vue.extend({
  template: 'Посмотрите на всех, кто тут работает!'
});

router.map({
  '/': {
    component: Home
  },
  '/people': {
    component: People
  }
});

router.start(App, '#app');

Мы определили два возможных маршрута в нашем приложении и указали компонент для каждого из них.

Сборка HTML-страницы

Давайте создадим HTML-страницу для размещения нашего маршрутизатора. Этой странице не обязательно быть полностью пустой, как вы могли бы подумать. При использовании vue-router ваше приложение может содержать какой-либо код, и он не будет отключен из-за использования компонентов, например, это может быть панель навигации.

xml...
<div id="app">
  <a v-link="{ path: '/' }"><h1>Our company</h1></a>
  <ul class="navigation">
    <li><a v-link="{ path: '/people' }">People</a></li>
  </ul>

  <router-view></router-view>
</div>
...

Предположим, у этой страницы есть HTML-заголовок и блочные теги, а также она импортирует наши скрипты и зависимости где-нибудь в заголовке или подвале.

Здесь мы видим несколько важных вещей. Во-первых, когда мы запустили наш маршрутизатор в скрипте, мы связали его с '#app', поэтому нам надо создать элемент страницы с ID = «app», с которым мы свяжем наше Vue-приложение.

Во-вторых, здесь использован Vue-синтаксис для ссылок — используется свойство v-link и передаётся в JSON-объект. Мы будем делать так: { path: '/url-here' }.

Если открываемая в данный момент ссылка «активна» (открыта у пользователя), маршрутизатор применит для неё класс v-link-active, и вы сможете настроить для неё уникальный стиль. Также вы можете изменить этот класс или применять его для отдельных связанных элементов, таких как родительские div или li — вы можете узнать больше из документации.

И наконец, у нас есть компонент <router-view>, сюда будет приходить вывод каждого компонента.

Если вы зайдёте на эту страницу, и всё корректно загрузится, значит вы сделали своё первое одностраничное приложение с помощью vue-router!

Вы могли заметить, что сейчас в нём используется шебанг-стиль навигации, то есть все ваши маршруты начинаются с #!. Это можно отключить, мы поговорим об этом позже, но приготовьтесь, потребуется немного танцев с бубном.

Более продвинутое определение маршрута

Выше мы определили несколько довольно простых маршрутов. Давайте копнём немного глубже в направлении типов маршрутов, которые можно определить с помощью vue-router.

Параметры маршрута

Возможно вам понадобится определить более сложные маршруты, чем просто статические URL.
Мы будем вызывать URL, которые могут соответствовать нескольким «динамическим» URL. Посмотрим, как определить такой маршрут.

jsrouter.map({
  '/people/:personId': {
    component: {
      template: 'Person ID is {{$route.params.personId}}'
    }
  }
});

Из этого примера мы можем узнать несколько вещей.

Во-первых, мы видим, что vue-router отображает динамические параметры используя такой синтаксис: :paramName.

Во-вторых, мы видим, что vue-router позволяет при желании определять объекты компонентов в строку.

И в-третьих, мы видим, что у нас есть доступ к объекту $route со свойством params, который является объектом всех подходящих параметров динамических URL.

Маски сегментов маршрута

Когда надо определить сегмент динамического маршрута, который может подходить для нескольких сегментов, используйте в начале имени сегмента * вместо : :

jsrouter.map({
  '/people/*greedy' => {},
  '/people/*greedy/baz' => {},
});

Первое определение маршрута будет подходить для /people/a, /people/a/b, /people/a/b/c/d/e/f.

Второе определение маршрута будет подходить для /people/a/baz, /people/a/b/c/d/e/f/g/baz и т.д.

Оба будут возвращать сегмент greedy по маршруту $route.params.greedy, что эквивалентно полной строке для этого сегмента. /people/a/b/baz будет возвращать { greedy: 'a/b' }.

Именованные маршруты

Если вы когда-либо использовали маршруты Laravel, то вы уже знакомы с идеей — давать любому маршруту «имя», на которое можно ссылаться позже. С vue-router это тоже возможно:

jsrouter.map({
  '/people/:personId': {
    name: 'people.show',
    component: People
  }
});

Далее вы можете ссылаться на этот маршрут с помощью v-link:

xml<a v-link="{ name: 'people.show', params: { personId: 5 }}">Person 5</a>

Переход по маршруту в JavaScript

Мы рассмотрели, как v-link может заменять обычные ссылки, а что если вам надо инициировать событие перехода в вашем JavaScript? Тут вам поможет router.go():

jsrouter.go({ name: 'people.show', params: { personId: 5 }});

Также вы можете использовать router.replace(), который работает так же, но при этом не создаёт новой записи в истории браузера.

Настройки маршрутизатора

Когда вы создаёте экземпляр объекта маршрутизатора в начале вашего JavaScript-файла, вы можете передать в него несколько параметров для настройки.

  • hashbang — если задать значение false, система будет использовать настоящие URL (/people) вместо шебанга (/#!/people). Если вы сделаете так, то вам надо будет включить history и соответственно настроить свой сервер.
  • history — использует момент отправки в браузере для обновления истории посещений в нём при переходах на сайте. Требует правильной настройки вашего сервера.
  • root — если ваше приложение находится не в корне на сервере, то задайте это свойство для указания правильной подпапки, в которой находится приложение. Например, если ваше приложение находится в /app, то задайте значение /app, тогда vue-router будет генерировать соответствующие URL — /app/people вместо /people.

Если вы используете это приложение внутри Laravel-приложения, то вместо настройки nginx или Apache для обработки без-шебангового состояния отправки вы можете настроить своё Laravel-приложение для его обработки. Просто установите маршрут для захвата всех валидных URL и передачи их в представление, выводящее ваш Vue-код:

js Route::get('/{vue_capture?}', function () {
   return view('home');
 })->where('vue_capture', '[\/\w\.-]*');

Получение информации маршрута в ваших компонентах

У каждого компонента в вашем приложении будет доступ к this.$route, который является «контекстным объектом маршрута» и предоставляет свойства, которые могут быть полезны для получения информации о вашем маршруте. У ваших шаблонов тоже будет доступ к этому объекту через $route.

  • $route.path эквивалентен абсолютному пути, например, /people
  • $route.params содержит пары ключ/значение ваших динамических разделов, например, { personId: 5 }
  • $route.query содержит пары ключ/значение вашей строки запроса, например, /people?sortBy=names будет возвращать { sortBy : lastName }
  • $route.router возвращает экземпляр vue-router
  • $route.matched возвращает объекты конфигурации маршрута для каждого подходящего сегмента в текущем маршруте
  • $route.name возвращает имя текущего маршрута, если таковое имеется

Вы также можете передать в свои компоненты произвольные данные, передав их в определение маршрута. Например, я хочу, чтобы некоторые секции моего приложения были доступны только администратору, тогда я передаю это в виде флага в определение маршрута, а внутри компонента проверю его наличие как $route.adminOnly.

jsrouter.map({
  '/secret-admin-panels': {
    component: SecretDashboard,
    adminOnly: true
  }
});

Настройка хуков

Я мог бы проверять свойство $route.adminOnly в своих компонентах, но ещё лучше, если это будет обработано до того, как пользователь получит доступ к компоненту, при помощи посредника. При использовании vue-router это будут хуки маршрута, такие как beforeEach:

js// Пример проверки доступа пользователя
var MyUser = { admin: false };

router.beforeEach(function (transition) {
  if (transition.to.adminOnly && ! MyUser.admin) {
    transition.redirect('/login');
  } else {
    transition.next();
  }
});

Как видите, мы перехватываем запрос перед отрисовкой компонента. Мы можем разрешить дальнейший переход с помощью transition.next(), а также мы можем перехватить пользователя и перенаправить или отменить переход — transition.abort().

Существует также хук afterEach().

Разное

Ещё несколько последних замечаний.

Первое, <router-view> может быть передан точно так же, как и любой другой страничный компонент.

Второе, для Vue есть полное описание переходов, которое можно использовать для определения визуального и функционального поведения при переходах между страницами.

Третье, эта статья охватывает далеко не всё, загляните в документацию.

Заключение

Вот теперь всё. Вы увидели насколько просто настроить своё первое одностраничное приложение при помощи Vue и vue-router, и насколько плавный переход от единственного компонента к одностраничному приложению.

Если хотите посмотреть на (какой-нибудь) работающий пример использования vue-router, то можете взглянуть на обучающее приложение Suggestive, над которым я сейчас работаю.

Как вы считаете, полезен ли этот материал? Да Нет

Комментарии (2)

des1roer

а можно без npm? я хочу в script подключить vue-router и по клику на кнопку отображать другую страницу. может мне и роутер в данном случае не нужен? я вообще то слабо представляю зачем он?

Explorer

Привет. Если правильно тебя понимаю, ты можешь сделать каждую страницу своего сайта отдельным одно-страничным приложением, в этом случае ты вполне можешь обойтись и без роутера.

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.