Первоначальная версия

This commit is contained in:
2019-06-09 23:43:12 +03:00
parent a0fa2798d9
commit 9f4cda9e64
25 changed files with 9394 additions and 0 deletions

9
public/data/id1.html Normal file
View File

@@ -0,0 +1,9 @@
<h1>Введение</h1>
<p>
Привет! Данный самоучитель появился в результате желания освоить Vue.js. Я решил что решать абстрактные задачи
и записывать свои мысли в блокнот менее интересно чем создать мини-сайт справочник, описывающий процесс его же
создания.
</p>
<p>
Надеюсь мои заметки окажутся полезными и вам.
</p>

37
public/data/id201.html Normal file
View File

@@ -0,0 +1,37 @@
<h1>Подготовка среды разработки</h1>
<h2>Программное обеспечение</h2>
<p>
Что вам потребуется для создания первого приложения на Vue.js? Самый минимум - это текстовый редактор и
наличие интернета, но мы пойдём другим путём, возьмём инструменты разработки для взрослых, а именно:
менеджер пакетов npm или yarn, систему контроля версий Git и редактор исходного кода (В моём случае это
Visual Stido Code, но вы можете использовать любой другой).
</p>
<p>
Нужен ли вам yarn - решайте сами, сравнений в интернете много, вот одно из них:
<a href="http://prgssr.ru/development/yarn-ili-npm-vse-chto-vam-nuzhno-znat.html" target="_blank">Yarn
или npm: все, что вам нужно знать о них</a>. Я в данном руководстве буду его использовать, но если вы
решили его не устанавливать, то перевести команды в формат npm не составит труда.
</p>
<h3>Ссылки</h3>
<p>
<ol>
<li>npm: <a target="_blank" href="https://www.npmjs.com/get-npm">https://www.npmjs.com/get-npm</a></li>
<li>yarn: <a target="_blank" href="https://www.yarnpkg.com/ru/docs/install#windows-stable">https://www.yarnpkg.com/ru/docs/install#windows-stable</a></li>
<li>Git: <a target="_blank" href="https://git-scm.com/downloads">https://git-scm.com/downloads</a></li>
<li>Visual Studio Code: <a target="_blank" href="https://code.visualstudio.com/download">https://code.visualstudio.com/download</a></li>
</ol>
</p>
<h3>Установка vue-cli</h3>
<p>
Установив менеджер пакетов, перейдём к установке vue-cli с помощью которой в будущем будем создавать наши
великие и не очень проекты. Делается это командой <code>yarn global add @vue/cli</code> если вы решили
использовать yarn или <code>npm install @vue/cli -g</code> если выбор пал на npm. Также имеет смысл сразу
установить пакет vue/cli-upgrade для обновления vue-cli в будущем.
</p>
<p>
На этом установка инструментария для дальнейшей работы завершена, переходим к настройке среды разработки
и созданию нового проекта.
</p>

17
public/data/id202.html Normal file
View File

@@ -0,0 +1,17 @@
<h1>Подготовка среды разработки</h1>
<h2>Расширения Visual Studio Code</h2>
<p>
Если вы выбрали другой редактор кода, смело можете пропустить данную часть.
</p>
<p>
<b>Bookmarks.</b> Позволяет создавать закладки с описаниями, что очень помогает в процессе разработки.
</p>
<p>
<b>GitLens.</b> Очень упрощает работу с Git непосредственно из Visual Studio.
</p>
<p>
<b>Vue 2 Snippets.</b> Сниппеты для Vue 2.
</p>
<p>
<b>vuetify-vscode.</b> Сниппеты для Vuetify.
</p>

26
public/data/id301.html Normal file
View File

@@ -0,0 +1,26 @@
<h1>Создание проекта</h1>
<p>
Создать проект можно двумя способами: из терминала или при помощи веб-интерфейса. Рассмотрим оба способа.
<ol>
<li>Из терминала, для этого следует выполнить команду <code>vue create _название_проекта_</code></li>
<li>В веб-интерфейсе, запустив его командой <code>vue ui</code></li>
</ol>
</p>
<p>
При создании проекта выберите параметры по умолчанию с установкой babel и eslint.
</p>
<p>
Каркас приложения мы создали, можно посмотреть что получилось выполнив команду <code>yarn serve</code> или
<code>npm run serve</code>. Вдоволь налюбовавшись результатом, добавим к проекту библиотеку интерфейса
Vuetify, выполнив команду <code>vue add vuetify</code>. Установщик задаст вам единственный вопрос - какие
предустановки вы хотите выбрать (Choose a preset), нас устроит набо по умолчанию (default).
</p>
<p>
запустив <code>yarn serve</code> сейчас, вы увидите, что внешний вид нашего приложения несколько изменился,
в нём появились компоненты библиотеки Vuetify. Этот вариант мы и возьмём за основу нашего приложения.
</p>
<h2>Клонирование проекта</h2>
<p>
Текущую версию проекта можно также получить с Git, для этого создайте каталог проекта, перейдите в него
и клонируйте командой <code>git clone https://home.cainet.info:3000/cai/VueJS/</code>.
</p>

237
public/data/id302.html Normal file
View File

@@ -0,0 +1,237 @@
<h1>Создание компонента оглавления</h1>
<p>
Первое что мы сделаем в нашем проекте - это компопнент оглавления с поиском главы, тот что вы видите сейчас слева
от данного текста. Но сначала удалим всё ненужное из сгенерированного на предыдущем шаге шаблона.
</p>
<p>
А ненужное - это компонент HelloWorld и все ссылки на него. Смело удаляйте файл HelloWorld.vue из каталога
<code>src/components/</code>, а файл App.vue приведите к следующему виду:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;v-app>
&lt;v-toolbar app>
&lt;v-toolbar-title class="headline text-uppercase">
&lt;span>Vue.js:&lt;/span>
&lt;span class="font-weight-light">Самоучитель&lt;/span>
&lt;/v-toolbar-title>
&lt;v-spacer>&lt;/v-spacer>
&lt;v-btn
flat
href="https://github.com/vuetifyjs/vuetify/releases/latest"
target="_blank"
>
&lt;span class="mr-2">Актуальная версия</span>
&lt;/v-btn>
&lt;/v-toolbar>
&lt;v-content>
&lt;/v-content>
&lt;/v-app>
&lt;/template>
&lt;script>
export default {
name: 'App',
components: {
},
data () {
return {
}
}
}
&lt;/script>
</pre>
</div>
</p>
<p>
Vuetify неплохо документирован и имеет множество примеров, одним из них мы и воспользуемся при создании компонента
оглавления. За основу возьмём один из примеров со страницы
<a href="https://next.vuetifyjs.com/ru/components/treeview" target="blank">https://next.vuetifyjs.com/ru/components/treeview</a> и
приведём его к следующему виду:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;v-card class="mx-auto">
&lt;v-sheet class="pa-3 primary lighten-2">
&lt;v-text-field
v-model="search"
label="Поиск по названию главы"
dark
flat
solo-inverted
hide-details
clearable
clear-icon="mdi-close-circle-outline"
>
&lt;/v-text-field>
&lt;v-checkbox
v-model="caseSensitive"
dark
hide-details
label="С учётом регистра"
>
&lt;/v-checkbox>
&lt;/v-sheet>
&lt;v-card-text>
&lt;v-treeview
:active.sync="active"
:filter="filter"
:items="items"
:open.sync="open"
:search="search"
activatable
active-class="primary--text"
open-on-click
>
&lt;template v-slot:prepend="{ item }">
&lt;v-icon
v-if="item.children"
v-text="`mdi-${item.id === 1 ? 'home-variant' : 'folder-network'}`"
>
&lt;/v-icon>
&lt;/template>
&lt;/v-treeview>
&lt;/v-card-text>
&lt;/v-card>
&lt;/template>
&lt;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
}
}
}
&lt;/script>
</pre>
</div>
</p>
<p>
Компонент готов, но если вы запустите приложение на исполнение, то никаких изменений не увидите, ведь мы не
добавили его в само приложение. Этим сейчас и займёмся. Откройте файл App.vue и в блок <code>&lt;v-content>
&lt;/v-content></code> добавьте наш компонент <code>&lt;TOC/></code>. Уже запустили просмотр? Ну и как?
Ничего нового? А всё потому, что мы не импортировали его в приложение, срочно исправляем это досадное
недоразумение добавлением в блок <code>&lt;script>&lt;/script></code> строки
<code>import TOC from './components/TOC'</code> и чуть ниже в <code>components: {},</code> строку
<code>TOC</code>. В итоге App.vue должен выглядеть следующим образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;v-app>
&lt;v-toolbar app>
&lt;v-toolbar-title class="headline text-uppercase">
&lt;span>Vue.js:&lt;/span>
&lt;span class="font-weight-light">Самоучитель&lt;/span>
&lt;/v-toolbar-title>
&lt;v-spacer>&lt;/v-spacer>
&lt;v-btn
flat
href="https://github.com/vuetifyjs/vuetify/releases/latest"
target="_blank"
>
&lt;span class="mr-2">Актуальная версия</span>
&lt;/v-btn>
&lt;/v-toolbar>
&lt;v-content>
&lt;TOC/>
&lt;/v-content>
&lt;/v-app>
&lt;/template>
&lt;script>
import TOC from './components/TOC'
export default {
name: 'App',
components: {
TOC
},
data () {
return {
}
}
}
&lt;/script>
</pre>
</div>
</p>
<p>
Запустили? Круто же? =) Идём дальше.
</p>
<p>
Нам надо чтобы оглавление было во всю ширину экрана только на смартфонах, на компьютере это выглядит как минимум
странно, изменим разметку в файле App.vue, создадим одну колонку шириной 4 для оглавления и одну шириной 8 для
текста. Про двенадцатиточечную систему сеток Vutify можно прочитать тут:
<a href="https://vuetifyjs.com/ru/framework/grid" target="_blank">https://vuetifyjs.com/ru/framework/grid</a>.
Приведём блок &lt;v-content>&lt;/v-content> к следующему виду:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;v-content>
&lt;v-container fluid fill-height grid-list-md>
&lt;v-layout row wrap full-height>
&lt;v-flex sm4>
&lt;TOC/>
&lt;/v-flex>
&lt;v-flex sm8 v-html="text">&lt;/v-flex>
&lt;/v-layout>
&lt;/v-container>
&lt;/v-content>
</pre>
</div>
</p>
<p>
В блок <code>data()</code> добавьте строку <code>text: ""</code> так как выше, в строке
<code>&lt;v-flex sm8 v-html="text">&lt;/v-flex></code> мы директивой <code>v-html="text"</code> указали Vue, что
оон должен в качестве содержимого блока брать значение свойства text, и если мы его не добавим в объект нашего
приложения, то Vue будет ругаться нехорошими словами.
</p>
<p>
Готово! Почти идеально... Почему почти? Попробуйте уменьшить размер окна браузера и на определённом этапе буквы
вылезут за пределы блока меню... Непорядок! К счастью, исправить сиё недоразумение несложно, просто добавьте в
наш компонент (TOC.vue) блок стилей:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;style>
.v-treeview-node__content, .v-treeview-node__label {
flex-shrink: 1;
}
.v-treeview-node__root {
height: auto;
}
&lt;/style>
</pre>
</div>
</p>
<p>
Отлично! Теперь всё выглядит как надо и можно переходить к следующему шагу.
</p>

126
public/data/id303.html Normal file
View File

@@ -0,0 +1,126 @@
<h1>Загрузка данных</h1>
<p>
В созданном нами компоненте есть один ощутимый недостаток - данные в нём зашиты намертво и чтобы добавить
новую главу, придётся перекомпилировать всё приложение, а так дела не делаются. Сейчас мы добавим возможность
хранения данных во внешних файлах и будем загружать их по мере надобности.
</p>
<p>
Для начала нам понадобится Axios (<a href="https://yarnpkg.com/ru/package/axios" target="_blank">
https://yarnpkg.com/ru/package/axios</a>), именно с его помощью мы будем загружать наши json и html файлы.
Установим его командой <code>yarn add axios vue-axios</code>, после чего добавим в main.js строки для его
подключения. Выглядеть он у вас должен следующим образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
import Vue from 'vue'
import Axios from 'axios'
import VueAxios from 'vue-axios'
import './plugins/vuetify'
import App from './App.vue'
Vue.config.productionTip = false
Vue.use(VueAxios, Axios)
new Vue({
render: h => h(App),
}).$mount('#app')
</pre>
</div>
</p>
<p>
Вот теперь можно взяться за загрузку внешних данных. Для начала уберём из нашего компонента (TOC.vue) все данные
о разделах, для этого строку items в блоке data приведём к виду <code>items: []</code>, после чего перейдём к
App.vue и в секцию export добавим <code>mounted () {}</code>. Здесь мы в дальнейшем добавим код, исполняемый при
запуске нашего приложения. Блок <code>&lt;script>&lt;/script></code> должен выглядеть следующим образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;script>
import TOC from './components/TOC'
export default {
name: 'App',
components: {
TOC
},
data () {
return {
}
},
mounted () {
}
}
&lt;/script>
</pre>
</div>
</p>
<p>
Помимо этого нам надо немного изменить тег нашего оглавления, добавить в него <code>ref="TOC"</code>, после
чего выглядеть он должен следующим образом: <code>&lt;TOC ref="TOC"/></code>. Нужно нам это для того чтобы
мы могли обращаться к конкретному экземпляру созданного нами компонента.
</p>
<p>
Итак, добавим в секцию <code>mounted</code> код загрузки оглавления:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
mounted () {
this.axios.get("data/toc.json")
.then(response => {
this.$refs.TOC.items = response.data;
})
.catch(error => {
console.log(error);
});
}
</pre>
</div>
</p>
<p>
Готово! Всё работает, убедиться в этом можете открыв консоль браузера и обнаружив там ошибку "Request failed with
status code 404". Чтобы от неё избавиться, создайте в каталоге public/data файл toc.json и заполните его данными
о разделах. Готовый файл можно получить по ссылке <a href="../data/toc.json" target="_blank">/data/toc.json</a>
и сохранить его в <code>public/data/toc.json</code>. После этого оглавление будет загружаться из него.
</p>
<p>
Оглавление у нас есть, осталось реализовать загрузку статей. Для того чтобы сделать это, погрузимся немного в
принципы работы нашего компонента. Каждый раз при выборе элемента, у компонента изменяется свойство active и
нам надо отслеживать его изменение в App.vue. Для этого добавим в mounted файла App.vue следующий код:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
this.$watch(
"$refs.TOC.active",
(newVal, oldVal) => {
if (newVal.length) {
this.axios.get("data/id" + newVal + ".html")
.then(response => {
this.text = response.data;
})
.catch(error => {
console.log(error);
});
}
}
);
</pre>
</div>
</p>
<p>
Остаётся только создать файлы с содержимым статей. Вы можете скачать их из git или по следующим ссылкам:
<ul>
<li><a href="../data/id1.html" target="_blank">/data/id1.html</a></li>
<li><a href="../data/id201.html" target="_blank">/data/id201.html</a></li>
<li><a href="../data/id202.html" target="_blank">/data/id202.html</a></li>
<li><a href="../data/id301.html" target="_blank">/data/id301.html</a></li>
<li><a href="../data/id302.html" target="_blank">/data/id302.html</a></li>
<li><a href="../data/id303.html" target="_blank">/data/id303.html</a></li>
</ul>
Разместите данные файлы в public/data/. Теперь приложение выполняет все свои основные задачи.
</p>
<p>
А теперь попробуйте самостоятельно добавить при старте приложения загрузку и отображение информации о нём.
Файл с информацией можно взять на git или по следующей ссылке:
<a href="../data/start.html" target="_blank">/data/start.html</a>.
</p>

207
public/data/id304.html Normal file
View File

@@ -0,0 +1,207 @@
<h1>Добавление диалогов</h1>
<h2>Диалог с сообщением</h2>
<p>
Некоторые ссылки в нашем приложении пока ведут в никуда и единственная реакция на щелчок по ним - это сообщение
в консоли, что не особо информативно, исправим этот недочёт. Создадим новый компонент MessageDialog.vue и, не
изобретая велосипедов, возьмём готовое решение для модального диалога из документации к Vuetify:
<a href="https://vuetifyjs.com/ru/components/dialogs" target="_blank">https://vuetifyjs.com/ru/components/dialogs</a>,
немного его модифицировав:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;v-layout row justify-center>
&lt;v-dialog
v-model="dialog"
persistent
max-width="290"
>
&lt;v-card>
&lt;v-card-title class="headline">{{ title }}&lt;/v-card-title>
&lt;v-card-text>{{ text }}&lt;/v-card-text>
&lt;v-card-actions>
&lt;v-spacer>&lt;/v-spacer>
&lt;v-btn color="green darken-1" flat @click="dialog = false">Ok&lt;/v-btn>
&lt;/v-card-actions>
&lt;/v-card>
&lt;/v-dialog>
&lt;/v-layout>
&lt;/template>
&lt;script>
export default {
data () {
return {
dialog: false,
title: "",
text: ""
}
}
}
&lt;/script>
</pre>
</div>
</p>
<p>
Подключите диалог, добавив в блок <code>&lt;script>&lt;/script></code> файла App.vue строку
<code>import MessageDialog from './components/MessageDialog'</code> и ниже в <code>components: {}</code>
строку <code>MessageDialog</code>. Начало блока <code>&lt;sctipt>&lt;/script></code> должно выглядеть следующим
образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;script>
import MessageDialog from './components/MessageDialog'
import TOC from './components/TOC'
export default {
name: 'App',
components: {
MessageDialog,
TOC
},
</pre>
</div>
</p>
<p>
В конец блока <code>&lt;v-app>&lt;/v-app></code> добавьте строку
<code>&ltMessageDialog ref="MessageDialog" /></code>, после чего останется только в коде скрипта добавить
в секции .catch каждого обращения к Axios строки вызова нашего диалога с сообщением об ошибке:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
.catch(error => {
console.log(error);
this.$refs.MessageDialog.title = "Ошибка";
this.$refs.MessageDialog.text = error;
this.$refs.MessageDialog.dialog = true;
});
</pre>
</div>
Теперь все ошибки при загрузке файлов будут показаны пользователю.
</p>
<h2>Диалог с индикатором загрузки</h2>
<p>
При медленном соединении наше приложение будет загружать данные молча, ни коим образом не оповещая пользователя о
том, что оно работает, это нехорошо, давайте выводить при загрузке индикатор. Создадим компонент LoadingDialog.vue
как всегда воспользовавшись шаблоном vuetify:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;div class="text-xs-center">
&lt;v-dialog
v-model="dialog"
hide-overlay
persistent
width="300"
>
&lt;v-card
color="primary"
dark
>
&lt;v-card-text>
Загружаю данные, ожидайте...
&lt;v-progress-linear
indeterminate
color="white"
class="mb-0"
>
&lt;/v-progress-linear>
&lt;/v-card-text>
&lt;/v-card>
&lt;/v-dialog>
&lt;/div>
&lt;/template>
&lt;script>
export default {
data () {
return {
dialog: false
}
},
watch: {
dialog (val) {
if (!val) return
}
}
}
&lt;/script>
</pre>
</div>
</p>
<p>
Предлагаю вам самостоятельно подключить его в App.vue, добавив нужные строки в блоки шаблона и скрипта. В шаблоне
значение ref установите равным "LoadingDialog".
</p>
<p>
Справились? Теперь добавим код для отображения и скрытия диалога при загрузке файла в секцию mounted:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;">
<pre>
mounted () {
this.$refs.LoadingDialog.dialog = true;
this.axios.get("data/start.html")
.then(response => {
this.text = response.data;
this.$refs.LoadingDialog.dialog = false;
})
.catch(error => {
this.$refs.LoadingDialog.dialog = false;
console.log(error);
this.$refs.MessageDialog.title = "Ошибка";
this.$refs.MessageDialog.text = error;
this.$refs.MessageDialog.dialog = true;
});
this.$refs.LoadingDialog.dialog = true;
this.axios.get("data/toc.json")
.then(response => {
this.$refs.TOC.items = response.data;
this.$refs.LoadingDialog.dialog = false;
})
.catch(error => {
this.$refs.LoadingDialog.dialog = false;
console.log(error);
this.$refs.MessageDialog.title = "Ошибка";
this.$refs.MessageDialog.text = error;
this.$refs.MessageDialog.dialog = true;
});
this.$watch(
"$refs.TOC.active",
(newVal, oldVal) => {
if (newVal.length) {
this.$refs.LoadingDialog.dialog = true;
this.axios.get("data/id" + newVal + ".html")
.then(response => {
this.text = response.data;
this.$refs.LoadingDialog.dialog = false;
})
.catch(error => {
this.$refs.LoadingDialog.dialog = false;
console.log(error);
this.$refs.MessageDialog.title = "Ошибка";
this.$refs.MessageDialog.text = error;
this.$refs.MessageDialog.dialog = true;
});
}
}
);
}
</pre>
</div>
</p>
<p>
Всё, теперь во время загрузки данных мы будем видеть сообщение с бегунком.
</p>
<p>
P.S. Текст данной части можно взять тут: <a href="../data/id304.html" target="_blank">/data/id304.html</a>
</p>
<p>
P.P.S. Финальную версию можно скомпилировать командой <code>yarn build</code>.
</p>

7
public/data/start.html Normal file
View File

@@ -0,0 +1,7 @@
<div class="text-xs-center">
<img src="../img/logo.png" alt="Логотип Vue.js">
<h1>Самоучитель Vue.js</h1>
<h2>&copy; Александр Чебыкин, 2019</h2>
<h3>Опубликовано под лицензией <a href="https://opensource.org/licenses/MIT">MIT</a></h3>
Git: <a href="https://home.cainet.info:3000/cai/VueJS/" target="_blank">https://home.cainet.info:3000/cai/VueJS/</a>
</div>

52
public/data/toc.json Normal file
View File

@@ -0,0 +1,52 @@
[
{
"id": 1,
"name": "Введение"
},
{
"id": 2,
"name": "Подготовка среды разработки",
"children": [
{
"id": 201,
"name": "Программное обеспечение"
},
{
"id": 202,
"name": "Расширения Visual Studio Code"
}
]
},
{
"id": 3,
"name": "Разработка",
"children": [
{
"id": 301,
"name": "Шаг 1. Создание проекта"
},
{
"id": 302,
"name": "Шаг 2. Создание компонента оглавления"
},
{
"id": 303,
"name": "Шаг 3. Загрузка данных"
},
{
"id": 304,
"name": "Шаг 4. Добавление диалогов"
}
]
},
{
"id": 99,
"name": "Дополнительная информация",
"children": [
{
"id": 9901,
"name": "Команды npm, yarn, vue-cli"
}
]
}
]