Первое что мы сделаем в нашем проекте - это компопнент оглавления с поиском главы, тот что вы видите сейчас слева от данного текста. Но сначала удалим всё ненужное из сгенерированного на предыдущем шаге шаблона.
А ненужное - это компонент HelloWorld и все ссылки на него. Смело удаляйте файл HelloWorld.vue из каталога
src/components/, а файл App.vue приведите к следующему виду:
<template>
<v-app>
<v-toolbar app>
<v-toolbar-title class="headline text-uppercase">
<span>Vue.js:</span>
<span class="font-weight-light">Самоучитель</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn
flat
href="https://github.com/vuetifyjs/vuetify/releases/latest"
target="_blank"
>
<span class="mr-2">Актуальная версия
</v-btn>
</v-toolbar>
<v-content>
</v-content>
</v-app>
</template>
<script>
export default {
name: 'App',
components: {
},
data () {
return {
}
}
}
</script>
Наш компонент будет использовать Material Design Icons, потому начнём с того, что подключим их. Для это выполните команду yarn add @mdi/font,
а после того как пакет установится, добавьте в самое начало файла main.js строку import '@mdi/font/css/materialdesignicons.css'. Всё, теперь
можно переходить к написанию самого компонента.
Vuetify неплохо документирован и имеет множество примеров, одним из них мы и воспользуемся при создании компонента оглавления. За основу возьмём один из примеров со страницы https://next.vuetifyjs.com/ru/components/treeview и приведём его к следующему виду:
<template>
<v-card class="mx-auto">
<v-sheet class="pa-3 primary lighten-2">
<v-text-field
v-model="search"
label="Поиск по названию главы"
dark
flat
solo-inverted
hide-details
clearable
clear-icon="mdi-close-circle-outline"
>
</v-text-field>
<v-checkbox
v-model="caseSensitive"
dark
hide-details
label="С учётом регистра"
>
</v-checkbox>
</v-sheet>
<v-card-text>
<v-treeview
:active.sync="active"
:filter="filter"
:items="items"
:open.sync="open"
:search="search"
activatable
active-class="primary--text"
open-on-click
>
<template v-slot:prepend="{ item }">
<v-icon
v-if="item.children"
v-text="`mdi-${open ? 'book-open-variant' : 'book-variant'}`"
>
</v-icon>
</template>
</v-treeview>
</v-card-text>
</v-card>
</template>
<script>
export default {
data: () => ({
active: [],
items: [
{
"id": 1,
"name": "Введение"
},
{
"id": 2,
"name": "Подготовка среды разработки",
"children": [
{
"id": 201,
"name": "Программное обеспечение"
}
]
}
],
open: [1],
search: null,
caseSensitive: false
}),
computed: {
filter () {
return this.caseSensitive
? (item, search, textKey) => item[textKey].indexOf(search) > -1
: undefined
}
}
}
</script>
Компонент готов, но если вы запустите приложение на исполнение, то никаких изменений не увидите, ведь мы не
добавили его в само приложение. Этим сейчас и займёмся. Откройте файл App.vue и в блок <v-content>
</v-content> добавьте наш компонент <TOC/>. Уже запустили просмотр? Ну и как?
Ничего нового? А всё потому, что мы не импортировали его в приложение, срочно исправляем это досадное
недоразумение добавлением в блок <script></script> строки
import TOC from './components/TOC' и чуть ниже в components: {}, строку
TOC. В итоге App.vue должен выглядеть следующим образом:
<template>
<v-app>
<v-toolbar app>
<v-toolbar-title class="headline text-uppercase">
<span>Vue.js:</span>
<span class="font-weight-light">Самоучитель</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn
flat
href="https://github.com/vuetifyjs/vuetify/releases/latest"
target="_blank"
>
<span class="mr-2">Актуальная версия
</v-btn>
</v-toolbar>
<v-content>
<TOC/>
</v-content>
</v-app>
</template>
<script>
import TOC from './components/TOC'
export default {
name: 'App',
components: {
TOC
},
data () {
return {
}
}
}
</script>
Запустили? Круто же? =) Идём дальше.
Нам надо чтобы оглавление было во всю ширину экрана только на смартфонах, на компьютере это выглядит как минимум странно, изменим разметку в файле App.vue, создадим одну колонку шириной 4 для оглавления и одну шириной 8 для текста. Про двенадцатиточечную систему сеток Vutify можно прочитать тут: https://vuetifyjs.com/ru/framework/grid. Приведём блок <v-content></v-content> к следующему виду:
<v-content>
<v-container fluid fill-height grid-list-md>
<v-layout row wrap full-height>
<v-flex sm5 md4 lg3>
<TOC/>
</v-flex>
<v-flex sm7 md8 lg9 v-html="text"></v-flex>
</v-layout>
</v-container>
</v-content>
В блок data() добавьте строку text: "" так как выше, в строке
<v-flex sm8 v-html="text"></v-flex> мы директивой v-html="text" указали Vue, что
оон должен в качестве содержимого блока брать значение свойства text, и если мы его не добавим в объект нашего
приложения, то Vue будет ругаться нехорошими словами.
Готово! Почти идеально... Почему почти? Попробуйте уменьшить размер окна браузера и на определённом этапе буквы вылезут за пределы блока меню... Непорядок! К счастью, исправить сиё недоразумение несложно, просто добавьте в наш компонент (TOC.vue) блок стилей:
<style>
.v-treeview-node__content, .v-treeview-node__label {
flex-shrink: 1;
}
.v-treeview-node__root {
height: auto;
}
</style>
Отлично! Теперь всё выглядит как надо и можно переходить к следующему шагу.