Новые уроки и полировка кода

This commit is contained in:
Alexander I. Chebykin 2019-06-10 22:06:26 +03:00
parent 644a854843
commit 64d0c9568b
17 changed files with 594 additions and 37 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) <year> <copyright holders> Copyright (c) 2019 Alexander I. Chebykin
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,3 +1,18 @@
# VueJS # VueJS
Самоучитель по VueJS Самоучитель по VueJS
## Установка
```
yarn install
```
### Компиляция и запуск для разработки
```
yarn run serve
```
### Сборка финальной версии
```
yarn run build
```

View File

@ -8,6 +8,7 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@mdi/font": "^3.6.95",
"axios": "^0.19.0", "axios": "^0.19.0",
"core-js": "^2.6.5", "core-js": "^2.6.5",
"vue": "^2.6.10", "vue": "^2.6.10",
@ -15,6 +16,7 @@
"vuetify": "^1.5.5" "vuetify": "^1.5.5"
}, },
"devDependencies": { "devDependencies": {
"@fortawesome/fontawesome-free": "^5.9.0",
"@vue/cli-plugin-babel": "^3.8.0", "@vue/cli-plugin-babel": "^3.8.0",
"@vue/cli-plugin-eslint": "^3.8.0", "@vue/cli-plugin-eslint": "^3.8.0",
"@vue/cli-service": "^3.8.0", "@vue/cli-service": "^3.8.0",

View File

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

View File

@ -6,7 +6,7 @@
<p> <p>
А ненужное - это компонент HelloWorld и все ссылки на него. Смело удаляйте файл HelloWorld.vue из каталога А ненужное - это компонент HelloWorld и все ссылки на него. Смело удаляйте файл HelloWorld.vue из каталога
<code>src/components/</code>, а файл App.vue приведите к следующему виду: <code>src/components/</code>, а файл App.vue приведите к следующему виду:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;template> &lt;template>
&lt;v-app> &lt;v-app>
@ -44,13 +44,18 @@
</pre> </pre>
</div> </div>
</p> </p>
<p>
Наш компонент будет использовать Material Design Icons, потому начнём с того, что подключим их. Для это выполните команду <kbd>yarn add @mdi/font</kbd>,
а после того как пакет установится, добавьте в самое начало файла main.js строку <code>import '@mdi/font/css/materialdesignicons.css'</code>. Всё, теперь
можно переходить к написанию самого компонента.
</p>
<p> <p>
Vuetify неплохо документирован и имеет множество примеров, одним из них мы и воспользуемся при создании компонента Vuetify неплохо документирован и имеет множество примеров, одним из них мы и воспользуемся при создании компонента
оглавления. За основу возьмём один из примеров со страницы оглавления. За основу возьмём один из примеров со страницы
<a href="https://next.vuetifyjs.com/ru/components/treeview" target="blank">https://next.vuetifyjs.com/ru/components/treeview</a> и <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;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;template> &lt;template>
&lt;v-card class="mx-auto"> &lt;v-card class="mx-auto">
@ -88,7 +93,7 @@
&lt;template v-slot:prepend="{ item }"> &lt;template v-slot:prepend="{ item }">
&lt;v-icon &lt;v-icon
v-if="item.children" v-if="item.children"
v-text="`mdi-${item.id === 1 ? 'home-variant' : 'folder-network'}`" v-text="`mdi-${open ? 'book-open-variant' : 'book-variant'}`"
> >
&lt;/v-icon> &lt;/v-icon>
&lt;/template> &lt;/template>
@ -142,7 +147,7 @@
недоразумение добавлением в блок <code>&lt;script>&lt;/script></code> строки недоразумение добавлением в блок <code>&lt;script>&lt;/script></code> строки
<code>import TOC from './components/TOC'</code> и чуть ниже в <code>components: {},</code> строку <code>import TOC from './components/TOC'</code> и чуть ниже в <code>components: {},</code> строку
<code>TOC</code>. В итоге App.vue должен выглядеть следующим образом: <code>TOC</code>. В итоге App.vue должен выглядеть следующим образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;template> &lt;template>
&lt;v-app> &lt;v-app>
@ -193,15 +198,15 @@
текста. Про двенадцатиточечную систему сеток Vutify можно прочитать тут: текста. Про двенадцатиточечную систему сеток Vutify можно прочитать тут:
<a href="https://vuetifyjs.com/ru/framework/grid" target="_blank">https://vuetifyjs.com/ru/framework/grid</a>. <a href="https://vuetifyjs.com/ru/framework/grid" target="_blank">https://vuetifyjs.com/ru/framework/grid</a>.
Приведём блок &lt;v-content>&lt;/v-content> к следующему виду: Приведём блок &lt;v-content>&lt;/v-content> к следующему виду:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;v-content> &lt;v-content>
&lt;v-container fluid fill-height grid-list-md> &lt;v-container fluid fill-height grid-list-md>
&lt;v-layout row wrap full-height> &lt;v-layout row wrap full-height>
&lt;v-flex sm4> &lt;v-flex sm5 md4 lg3>
&lt;TOC/> &lt;TOC/>
&lt;/v-flex> &lt;/v-flex>
&lt;v-flex sm8 v-html="text">&lt;/v-flex> &lt;v-flex sm7 md8 lg9 v-html="text">&lt;/v-flex>
&lt;/v-layout> &lt;/v-layout>
&lt;/v-container> &lt;/v-container>
&lt;/v-content> &lt;/v-content>
@ -219,7 +224,7 @@
вылезут за пределы блока меню... Непорядок! К счастью, исправить сиё недоразумение несложно, просто добавьте в вылезут за пределы блока меню... Непорядок! К счастью, исправить сиё недоразумение несложно, просто добавьте в
наш компонент (TOC.vue) блок стилей: наш компонент (TOC.vue) блок стилей:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;style> &lt;style>
.v-treeview-node__content, .v-treeview-node__label { .v-treeview-node__content, .v-treeview-node__label {

View File

@ -7,9 +7,9 @@
<p> <p>
Для начала нам понадобится Axios (<a href="https://yarnpkg.com/ru/package/axios" target="_blank"> Для начала нам понадобится Axios (<a href="https://yarnpkg.com/ru/package/axios" target="_blank">
https://yarnpkg.com/ru/package/axios</a>), именно с его помощью мы будем загружать наши json и html файлы. https://yarnpkg.com/ru/package/axios</a>), именно с его помощью мы будем загружать наши json и html файлы.
Установим его командой <code>yarn add axios vue-axios</code>, после чего добавим в main.js строки для его Установим его командой <kbd>yarn add axios vue-axios</kbd>, после чего добавим в main.js строки для его
подключения. Выглядеть он у вас должен следующим образом: подключения. Выглядеть он у вас должен следующим образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
import Vue from 'vue' import Vue from 'vue'
import Axios from 'axios' import Axios from 'axios'
@ -32,7 +32,7 @@ new Vue({
о разделах, для этого строку items в блоке data приведём к виду <code>items: []</code>, после чего перейдём к о разделах, для этого строку items в блоке data приведём к виду <code>items: []</code>, после чего перейдём к
App.vue и в секцию export добавим <code>mounted () {}</code>. Здесь мы в дальнейшем добавим код, исполняемый при App.vue и в секцию export добавим <code>mounted () {}</code>. Здесь мы в дальнейшем добавим код, исполняемый при
запуске нашего приложения. Блок <code>&lt;script>&lt;/script></code> должен выглядеть следующим образом: запуске нашего приложения. Блок <code>&lt;script>&lt;/script></code> должен выглядеть следующим образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;script> &lt;script>
import TOC from './components/TOC' import TOC from './components/TOC'
@ -63,7 +63,7 @@ new Vue({
</p> </p>
<p> <p>
Итак, добавим в секцию <code>mounted</code> код загрузки оглавления: Итак, добавим в секцию <code>mounted</code> код загрузки оглавления:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
mounted () { mounted () {
this.axios.get("data/toc.json") this.axios.get("data/toc.json")
@ -88,7 +88,7 @@ mounted () {
принципы работы нашего компонента. Каждый раз при выборе элемента, у компонента изменяется свойство active и принципы работы нашего компонента. Каждый раз при выборе элемента, у компонента изменяется свойство active и
нам надо отслеживать его изменение в App.vue. Для этого добавим в mounted файла App.vue следующий код: нам надо отслеживать его изменение в App.vue. Для этого добавим в mounted файла App.vue следующий код:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
this.$watch( this.$watch(
"$refs.TOC.active", "$refs.TOC.active",

View File

@ -7,7 +7,7 @@
<a href="https://vuetifyjs.com/ru/components/dialogs" target="_blank">https://vuetifyjs.com/ru/components/dialogs</a>, <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;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;template> &lt;template>
&lt;v-layout row justify-center> &lt;v-layout row justify-center>
@ -21,7 +21,7 @@
&lt;v-card-text>{{ text }}&lt;/v-card-text> &lt;v-card-text>{{ text }}&lt;/v-card-text>
&lt;v-card-actions> &lt;v-card-actions>
&lt;v-spacer>&lt;/v-spacer> &lt;v-spacer>&lt;/v-spacer>
&lt;v-btn color="green darken-1" flat @click="dialog = false">Ok&lt;/v-btn> &lt;v-btn color="primary" flat @click="dialog = false">Ok&lt;/v-btn>
&lt;/v-card-actions> &lt;/v-card-actions>
&lt;/v-card> &lt;/v-card>
&lt;/v-dialog> &lt;/v-dialog>
@ -48,7 +48,7 @@
строку <code>MessageDialog</code>. Начало блока <code>&lt;sctipt>&lt;/script></code> должно выглядеть следующим строку <code>MessageDialog</code>. Начало блока <code>&lt;sctipt>&lt;/script></code> должно выглядеть следующим
образом: образом:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;script> &lt;script>
import MessageDialog from './components/MessageDialog' import MessageDialog from './components/MessageDialog'
@ -68,7 +68,7 @@
<code>&ltMessageDialog ref="MessageDialog" /></code>, после чего останется только в коде скрипта добавить <code>&ltMessageDialog ref="MessageDialog" /></code>, после чего останется только в коде скрипта добавить
в секции .catch каждого обращения к Axios строки вызова нашего диалога с сообщением об ошибке: в секции .catch каждого обращения к Axios строки вызова нашего диалога с сообщением об ошибке:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
.catch(error => { .catch(error => {
console.log(error); console.log(error);
@ -87,7 +87,7 @@
том, что оно работает, это нехорошо, давайте выводить при загрузке индикатор. Создадим компонент LoadingDialog.vue том, что оно работает, это нехорошо, давайте выводить при загрузке индикатор. Создадим компонент LoadingDialog.vue
как всегда воспользовавшись шаблоном vuetify: как всегда воспользовавшись шаблоном vuetify:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
&lt;template> &lt;template>
&lt;div class="text-xs-center"> &lt;div class="text-xs-center">
@ -139,7 +139,7 @@
</p> </p>
<p> <p>
Справились? Теперь добавим код для отображения и скрытия диалога при загрузке файла в секцию mounted: Справились? Теперь добавим код для отображения и скрытия диалога при загрузке файла в секцию mounted:
<div class="grey lighten-2" style="overflow-x: auto; border-radius: 5px;"> <div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre> <pre>
mounted () { mounted () {
this.$refs.LoadingDialog.dialog = true; this.$refs.LoadingDialog.dialog = true;
@ -203,5 +203,5 @@ mounted () {
P.S. Текст данной части можно взять тут: <a href="../data/id304.html" target="_blank">/data/id304.html</a> P.S. Текст данной части можно взять тут: <a href="../data/id304.html" target="_blank">/data/id304.html</a>
</p> </p>
<p> <p>
P.P.S. Финальную версию можно скомпилировать командой <code>yarn build</code>. P.P.S. Финальную версию можно скомпилировать командой <kbd>yarn build</kbd>.
</p> </p>

190
public/data/id305.html Normal file
View File

@ -0,0 +1,190 @@
<h1>Цветовые схемы</h1>
<p>
Наша программа получилась такая светлая-красивая, но в темноте пользоваться ей неудобно, яркий свет от экрана слишком бьёт по глазам, предлагаю
<s>перейти на тёмную сторону</s> сделать тёмный вариант интерфейса.
</p>
<p>
Открывайте основной модуль нашего приложения App.vue. В блоке <code>&lt;script></code> найдите секцию <code>data ()</code> и добавьте в неё переменную dark
со значением по умолчанию равным false, это будет флаг использования тёмной версии интерфейса. После этого в блоке <code>&lt;template></code> измените
<code>&lt;v-app></code> на <code>&lt;v-app :dark="dark"></code>, этим мы свяжем наш флаг использования тёмной версии с назначением соответствующего
CSS-класса главному элементу программы.
</p>
<p>
Попробуйте изменить в <code>data ()</code> значение переменной dark на true, ваше приложение станет тёмным. Получилось? Теперь прикрутим меню с пунктом для
переключения вариантов интерфейса, для этого в конец блока <code>&lt;v-toolbar></code> добавим следующий код:
<div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;v-menu bottom left>
&lt;template v-slot:activator="{ on }">
&lt;v-btn
flat
icon
v-on="on"
>
&lt;v-icon>more_vert&lt;/v-icon>
&lt;/v-btn>
&lt;/template>
&lt;v-list>
&lt;v-list-tile>
&lt;v-list-tile-action>
&lt;v-switch v-model="dark" color="blue">&lt;/v-switch>
&lt;/v-list-tile-action>
&lt;v-list-tile-title>Тёмная схема&lt;/v-list-tile-title>
&lt;/v-list-tile>
&lt;/v-list>
&lt;/v-menu>
</pre>
</div>
Теперь у нас есть переключатель темы, но при каждой повторной загрузке тема всегда включается светлая, реализуем сохранение значения флага в
cookies, для этого в блоке <code>&lt;script></code> добавим секцию <code>watch</code> с кодом, отслеживающим изменение флага dark и сохраняющим
его значение в localSorage:
<div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre>
watch: {
dark (val) { localStorage.dark = val; }
}
</pre>
</div>
</p>
<p>
Сохранение сделали, сделаем и чтение сохранённой информации, добавив в секцию <code>mounted</code> строку
<code>this.dark = localStorage.dark ? JSON.parse(localStorage.dark) : false;</code>. После чего наш App.vue должен выглядеть следующим образом:
<div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;v-app :dark="dark">
&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://home.cainet.info:3000/cai/VueJS/"
target="_blank"
>
&lt;span class="mr-2">Актуальная версия&lt;/span>
&lt;/v-btn>
&lt;v-menu bottom left>
&lt;template v-slot:activator="{ on }">
&lt;v-btn
flat
icon
v-on="on"
>
&lt;v-icon>more_vert&lt;/v-icon>
&lt;/v-btn>
&lt;/template>
&lt;v-list>
&lt;v-list-tile>
&lt;v-list-tile-action>
&lt;v-switch v-model="dark" color="blue">&lt;/v-switch>
&lt;/v-list-tile-action>
&lt;v-list-tile-title>Тёмная схема&lt;/v-list-tile-title>
&lt;/v-list-tile>
&lt;/v-list>
&lt;/v-menu>
&lt;/v-toolbar>
&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 ref="TOC" />
&lt;/v-flex>
&lt;v-flex sm8 v-html="text">&lt;/v-flex>
&lt;/v-layout>
&lt;/v-container>
&lt;/v-content>
&lt;LoadingDialog ref="LoadingDialog" />
&lt;MessageDialog ref="MessageDialog" />
&lt;/v-app>
&lt;/template>
&lt;script>
import LoadingDialog from './components/LoadingDialog'
import MessageDialog from './components/MessageDialog'
import TOC from './components/TOC'
export default {
name: 'App',
components: {
LoadingDialog,
MessageDialog,
TOC
},
data () {
return {
dark: false,
docId: 0,
text: ""
}
},
mounted () {
this.$refs.LoadingDialog.dialog = true;
this.dark = localStorage.dark ? JSON.parse(localStorage.dark) : false;
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;
});
}
}
);
},
watch: {
dark (val) { localStorage.dark = val; }
}
}
&lt;/script>
</pre>
</div>
</p>

230
public/data/id306.html Normal file
View File

@ -0,0 +1,230 @@
<h1>Кнопка возвращения</h1>
<p>
Всё у нас вроде бы красиво, но вот проматывать каждый раз страницу вверх после прочтения урока неудобно, добавим кнопку возвращения к началу страницы.
Для этого нам потребуется в блок <code>&lt;v-app>&lt;/v-app></code> добавить код отображения самой кнопки:
<div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;v-fab-transition>
&lt;v-btn
v-show="scrolled"
color="blue"
@click="scrollToTop"
dark
fixed
bottom
right
fab
>
&lt;v-icon>keyboard_arrow_up&lt;/v-icon>
&lt;/v-btn>
&lt;/v-fab-transition>
</pre>
</div>
</p>
<p>
Как вы уже наверное заметили, кнопка у нас привязана к флагу отображения scrolled, это сделано для того чтобы она отображалась только когда требуется,
соответственно вам надо добавить данный флаг в блок data скрипта и назначить ему значение false. Сделали? Теперь добавим отслеживание прокрутки и
обработчик нажатия на кнопку - scrollToTop:
<div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre>
created () {
window.addEventListener('scroll', this.onScroll);
},
destroyed () {
window.removeEventListener('scroll', this.onScroll);
},
methods: {
onScroll () {
this.scrolled = window.scrollY > 0;
},
scrollToTop () {
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
}
}
</pre>
</div>
</p>
<p>
App.vue должен выглядеть следующим образом:
<div class="grey darken-3 white--text" style="overflow-x: auto; border-radius: 5px;">
<pre>
&lt;template>
&lt;v-app :dark="dark">
&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://home.cainet.info:3000/cai/VueJS/"
target="_blank"
>
&lt;span class="mr-2">Актуальная версия&lt;/span>
&lt;/v-btn>
&lt;v-menu bottom left>
&lt;template v-slot:activator="{ on }">
&lt;v-btn
flat
icon
v-on="on"
>
&lt;v-icon>more_vert&lt;/v-icon>
&lt;/v-btn>
&lt;/template>
&lt;v-list>
&lt;v-list-tile>
&lt;v-list-tile-action>
&lt;v-switch v-model="dark" color="blue">&lt;/v-switch>
&lt;/v-list-tile-action>
&lt;v-list-tile-title>Тёмная схема&lt;/v-list-tile-title>
&lt;/v-list-tile>
&lt;/v-list>
&lt;/v-menu>
&lt;/v-toolbar>
&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 ref="TOC" />
&lt;/v-flex>
&lt;v-flex sm8 v-html="text">&lt;/v-flex>
&lt;/v-layout>
&lt;/v-container>
&lt;/v-content>
&lt;v-fab-transition>
&lt;v-btn
v-show="scrolled"
color="blue"
@click="scrollToTop"
dark
fixed
bottom
right
fab
>
&lt;v-icon>keyboard_arrow_up&lt;/v-icon>
&lt;/v-btn>
&lt;/v-fab-transition>
&lt;LoadingDialog ref="LoadingDialog" />
&lt;MessageDialog ref="MessageDialog" />
&lt;/v-app>
&lt;/template>
&lt;script>
import LoadingDialog from './components/LoadingDialog'
import MessageDialog from './components/MessageDialog'
import TOC from './components/TOC'
export default {
name: 'App',
components: {
LoadingDialog,
MessageDialog,
TOC
},
data () {
return {
dark: false,
docId: 0,
scrolled: false,
text: ""
}
},
mounted () {
this.$refs.LoadingDialog.dialog = true;
this.dark = localStorage.dark ? JSON.parse(localStorage.dark) : false;
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;
});
}
}
);
},
watch: {
dark (val) { localStorage.dark = val; }
},
created () {
window.addEventListener('scroll', this.onScroll);
},
destroyed () {
window.removeEventListener('scroll', this.onScroll);
},
methods: {
onScroll () {
this.scrolled = window.scrollY > 0;
},
scrollToTop () {
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
}
}
}
&lt;/script>
</pre>
</div>
</p>

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

@ -0,0 +1,37 @@
<h1>Команды npm, yarn, vue-cli</h1>
<p>
Здесь я опишу некоторые основные команды, которые понадобятся нам во время обучения.
<table class="v-datatable v-table elevation-1">
<tr>
<th>Действие</th>
<th>npm</th>
<th>yarn</th>
<th>vue-cli</th>
</tr>
<tr>
<td>Установка vue-cli</td>
<td>npm install @vue/cli -g</td>
<td>yarn global add @vue/cli</td>
<td> - </td>
</tr>
<tr>
<td>Создание проекта</td>
<td>npm init (только инициализация проекта)</td>
<td>yarn init (только инициализация проекта)</td>
<td>vue create _название_проекта_ или при помощи WebUI: vue ui</td>
</tr>
<tr>
<td>Запуск dev-сервера</td>
<td>npm run serve</td>
<td>yarn serve</td>
<td> - </td>
</tr>
<tr>
<td>Компиляция финальной версии</td>
<td>npm build</td>
<td>yarn build</td>
<td> - </td>
</tr>
</table>
</p>

View File

@ -36,6 +36,14 @@
{ {
"id": 304, "id": 304,
"name": "Шаг 4. Добавление диалогов" "name": "Шаг 4. Добавление диалогов"
},
{
"id": 305,
"name": "Шаг 5. Цветовые схемы"
},
{
"id": 306,
"name": "Шаг 6. Кнопка возвращения"
} }
] ]
}, },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

View File

@ -13,18 +13,52 @@
> >
<span class="mr-2">Актуальная версия</span> <span class="mr-2">Актуальная версия</span>
</v-btn> </v-btn>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<v-btn
flat
icon
v-on="on"
>
<v-icon>more_vert</v-icon>
</v-btn>
</template>
<v-list>
<v-list-tile>
<v-list-tile-action>
<v-switch v-model="dark" color="blue"></v-switch>
</v-list-tile-action>
<v-list-tile-title>Тёмная схема</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar> </v-toolbar>
<v-content> <v-content>
<v-container fluid fill-height grid-list-md> <v-container fluid fill-height grid-list-md>
<v-layout row wrap full-height> <v-layout row wrap full-height>
<v-flex sm4> <v-flex sm5 md4 lg3>
<TOC ref="TOC" /> <TOC ref="TOC" />
</v-flex> </v-flex>
<v-flex sm8 v-html="text"></v-flex> <v-flex sm7 md8 lg9 v-html="text"></v-flex>
</v-layout> </v-layout>
</v-container> </v-container>
</v-content> </v-content>
<v-fab-transition>
<v-btn
v-show="scrolled"
color="blue"
@click="scrollToTop"
dark
fixed
bottom
right
fab
>
<v-icon>keyboard_arrow_up</v-icon>
</v-btn>
</v-fab-transition>
<LoadingDialog ref="LoadingDialog" /> <LoadingDialog ref="LoadingDialog" />
<MessageDialog ref="MessageDialog" /> <MessageDialog ref="MessageDialog" />
</v-app> </v-app>
@ -48,12 +82,14 @@
return { return {
dark: false, dark: false,
docId: 0, docId: 0,
scrolled: false,
text: "" text: ""
} }
}, },
mounted () { mounted () {
this.$refs.LoadingDialog.dialog = true; this.$refs.LoadingDialog.dialog = true;
this.dark = localStorage.dark ? JSON.parse(localStorage.dark) : false;
this.axios.get("data/start.html") this.axios.get("data/start.html")
.then(response => { .then(response => {
@ -103,9 +139,32 @@
} }
} }
); );
},
watch: {
dark (val) { localStorage.dark = val; }
},
created () {
window.addEventListener('scroll', this.onScroll);
},
destroyed () {
window.removeEventListener('scroll', this.onScroll);
},
methods: {
onScroll () {
this.scrolled = window.scrollY > 0;
},
scrollToTop () {
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
}
} }
} }
</script> </script>
<style>
</style>

View File

@ -10,7 +10,7 @@
<v-card-text>{{ text }}</v-card-text> <v-card-text>{{ text }}</v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn color="green darken-1" flat @click="dialog = false">Ok</v-btn> <v-btn color="primary" flat @click="dialog = false">Ok</v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>

View File

@ -31,10 +31,10 @@
active-class="primary--text" active-class="primary--text"
open-on-click open-on-click
> >
<template v-slot:prepend="{ item }"> <template v-slot:prepend="{ item, open }">
<v-icon <v-icon
v-if="item.children" v-if="item.children"
v-text="`mdi-${item.id === 1 ? 'home-variant' : 'folder-network'}`" v-text="`mdi-${open ? 'book-open-variant' : 'book-variant'}`"
> >
</v-icon> </v-icon>
</template> </template>

View File

@ -1,3 +1,4 @@
import '@mdi/font/css/materialdesignicons.css'
import Vue from 'vue' import Vue from 'vue'
import Axios from 'axios' import Axios from 'axios'
import VueAxios from 'vue-axios' import VueAxios from 'vue-axios'

View File

@ -667,6 +667,11 @@
lodash "^4.17.11" lodash "^4.17.11"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@fortawesome/fontawesome-free@^5.9.0":
version "5.9.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.9.0.tgz#1aa5c59efb1b8c6eb6277d1e3e8c8f31998b8c8e"
integrity sha512-g795BBEzM/Hq2SYNPm/NQTIp3IWd4eXSH0ds87Na2jnrAUFX3wkyZAI4Gwj9DOaWMuz2/01i8oWI7P7T/XLkhg==
"@hapi/address@2.x.x": "@hapi/address@2.x.x":
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a"
@ -702,6 +707,11 @@
cssnano-preset-default "^4.0.0" cssnano-preset-default "^4.0.0"
postcss "^7.0.0" postcss "^7.0.0"
"@mdi/font@^3.6.95":
version "3.6.95"
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-3.6.95.tgz#0bbde766ca2d94cfa0e469f25523b23d3112bdd3"
integrity sha512-wUbkF/RRCIh51TPzAL9qUeRSUFla9I3x1nGq62HkfWzIebRHbDY5HPaYCQuZO7398dWaLHTu4BwnBA58YbhfEA==
"@mrmlnc/readdir-enhanced@^2.2.1": "@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"