Компонент — это обособленная группа кода, которая является самодостаточной, и направлена на решение какой-либо одной задачи. Компоненты позволяют расширить базовый набор HTML-элементов, путем добавления новых, инкапсулируя при это их внутреннюю структуру. То есть, мы можем взять группу базовых HTML-тегов, добавить к ним необходимые CSS стили и логику на JavaScript, и упаковать все это в новый HTML-компонент для повторного использования в любом месте приложения.
Предыдущая статья: Знакомство с SCSS при работе с Vue.js
Создание компонентов очень важная тема при работе с одностраничными JavaScript приложениями, потому что они очень быстро разрастаются и становятся очень сложными. А основной принцип, которым мы должны руководствоваться при разработке приложения, это контроль сложности. Большую и сложную систему необходимо разделять на небольшие самостоятельные части, которые можно легко изменять независимо друг от друга. «Разделяй и властвуй». И с этой задачей прекрасно справляются компоненты.
Для начала создадим в папке App новую папку Components, в которую и будем помечать все отдельные файлы компонентов. В созданной папке добавим файл test-scss.vue со следующим содержимым.
<template> <div> <h1>Hello World!</h1> </div> </template> <script> export default { } </script>
В App.vue оставим только следующий код. Обратите внимание, что мы указали пока еще до конце не созданные компонент <test-scss>. Именно на это место будет подставлено содержимое, которое мы перенесли в отдельный файл.
<template> <test-scss></test-scss> </template> <script> export default { } </script>
Теперь идем в файл index.js, чтобы зарегистрировать созданный нами компонент и сделать его доступным для использования. Импортируем его с помощью команды import TestScss from ‘./Components/test-scss.vue’. Здесь мы указываем, что содержимое из созданного нами файла будет доступно под именем TestScss. И теперь непосредственно регистрируем компонент командой Vue.component(‘test-scss’, TestScss). Соответственно первый параметр это имя, по которому мы будем обращаться к компоненту (<test-scss>), а второй это сам компонент.
import Vue from 'vue' import VueRouter from 'vue-router' import App from './App.vue' import TestScss from './Components/test-scss.vue' Vue.config.productionTip = false Vue.use(VueRouter) Vue.component('test-scss', TestScss) const routes = [ { path: '/', component: App } ] const router = new VueRouter({ routes, mode: 'history' }) new Vue({ el: '#app', template: "<div><router-view></router-view></div>", router })
В итоге получаем ожидаемый результат.

Теперь перенесем в этот компонент все, что мы делали в предыдущем уроке, чтобы не загромождать App.vue, но при этом не потерять код. Обратите внимание, что необходимо изменить путь к файлам при импортировании (@import ‘../variables.scss’ и @import ‘../_h2partial’) , так как теперь путь ведется из другой папки.
test-scss.vue
<template> <div id="home"> <nav> <ul> <li>text 1</li> <li>text 2</li> </ul> </nav> <h1>Hello World!</h1> <h2>Привет, мир!</h2> <ul> <li>text 3</li> <li>text 4</li> </ul> <div class="box"> hello </div> <div class="success">OK</div> <div class="error">Error</div> <div class="marg">Отступ</div> <div class="wid">Светофор</div> </div> </template> <script> export default { } </script> <style lang="scss"> @import '../variables.scss'; nav { ul { margin: 0; padding: 0; color: red; list-style: none; } li { display: inline-block; } } h1 { color: $blue; } @import '../_h2partial'; @mixin border-r($radius) { -webkit-border-radius: $radius; -moz-border-radius: $radius; -ms-border-radius: $radius; border-radius: $radius; } .box { @include border-r(10px); border-style: solid; max-width: 100px; } .message { border: 1px solid #ccc; padding: 10px; color: #333; } .success { @extend .message; border-color: green; } .error { @extend .message; border-color: red; } .marg { margin-left: 100px + 20px; padding-top: 10% + 5%; } $width: 150px; .wid { @if($width < 200px) { color: red; } @else if ($width > 700) { color: green; } @else { color: yellow; } width: $width; } </style>
В результате мы добились внешнего вида, как он был и раньше, но теперь вся работа хранится в отдельном файле, который мы можем использовать при необходимости в любом месте приложения.
Но давайте рассмотрим более серьезный компонент. Для начала подключим CSS-фреймворк Bootstrap 4 версии. Он уже включен в набор наших пакетов, и нам достаточно добавить ссылку на в фале _Layout.cshtml.
<link rel="stylesheet" href="~/css/bootstrap.min.css" />
Теперь создадим еще один компонент question.vue в папке App/Components со следующим содержимым.
<template> <div id="question"> <div class="card text-center"> <div class="card-header">{{title}}</div> <div class="card-body"> <h5 class="card-title">{{subtitle}}</h5> <p class="card-text">{{text}}</p> </div> <div class="card-footer text-muted"> <input type="text" class="form-control" placeholder="Введите ответ" v-model="answer"></input> <a href="#" class="btn btn-primary" @click="showAnswer()">Ответить</a> </div> </div> </div> </template> <script> export default { data() { return { title: "Заголовок", subtitle: "Подзаголовок вопроса", text: "Текст вопроса", answer: "" } }, methods: { showAnswer() { alert(this.answer); } } } </script> <style lang="scss"> </style>
Давайте рассмотрим по-порядку. Мы можем использовать переменные из блока данных, указывая имя переменной в двойных фигурных скобках. Ниже приведены примеры получения значений из переменных:
<div class="card-header">{{title}}</div> <h5 class="card-title">{{subtitle}}</h5> <p class="card-text">{{text}}</p>
А вот так мы объявляем переменные в области данных:
data() { return { title: "Заголовок", subtitle: "Подзаголовок вопроса", text: "Текст вопроса", answer: "" } }
Мы также можем сохранять значение из поля ввода в переменных, для этого мы должны указать связь переменной и элемента формы с помощью команды v-model=»», в качестве аргумента указывается имя переменной. При изменении данных в поле ввода, они будут автоматически синхронизироваться с переменной, и наоборот.
<input type="text" class="form-control" placeholder="Введите ответ" v-model="answer"></input>
Ну и наконец мы можем объявлять методы и связывать их с событиями. Например, мы можем на добавить обработчик события на нажатие по ссылке с помощью команды @click=»». В качестве аргумента указывается имя метода и при необходимости параметры.
<a href="#" class="btn btn-primary" @click="showAnswer()">Ответить</a>
Сами же методы реализуются в блоке methods.
methods: { showAnswer() { alert(this.answer); } }
Аналогично тому, как мы ранее делали регистрируем новый компонент, а старый пока удалим за ненадобностью. Проверим результат работы приложения.

Исходный код доступен в репозитоии github.