Введение
Vue.js - это прогрессивный JavaScript-фреймворк для создания пользовательских интерфейсов. В этой статье мы рассмотрим основы Vue.js и научимся создавать современные веб-приложения.
Что такое Vue.js?
- Прогрессивность: Постепенное внедрение
- Реактивность: Автоматическое обновление
- Компонентность: Переиспользуемые UI-элементы
- Простота: Легкий для изучения
Начало работы
1. Установка и настройка
Создание проекта
1
2
3
4
5
6
7
8
9
10
11
| # Создание нового проекта
npm create vue@latest my-vue-app
# Переход в директорию проекта
cd my-vue-app
# Установка зависимостей
npm install
# Запуск приложения
npm run dev
|
Структура проекта
1
2
3
4
5
6
7
8
9
10
11
| my-vue-app/
├── node_modules/
├── public/
│ └── favicon.ico
├── src/
│ ├── components/
│ ├── views/
│ ├── App.vue
│ └── main.js
├── package.json
└── README.md
|
2. Базовый синтаксис
Создание компонента
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <template>
<div class="app">
<h1></h1>
<p></p>
</div>
</template>
<script>
export default {
data() {
return {
title: 'Привет, Vue!',
message: 'Это мое первое приложение'
}
}
}
</script>
<style>
.app {
padding: 20px;
}
</style>
|
Компоненты
1. Создание компонентов
Простой компонент
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| <template>
<button @click="handleClick">
</button>
</template>
<script>
export default {
props: {
text: {
type: String,
required: true
}
},
methods: {
handleClick() {
this.$emit('click')
}
}
}
</script>
|
Использование компонента
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <template>
<div>
<my-button
text="Нажми меня"
@click="onButtonClick"
/>
</div>
</template>
<script>
import MyButton from './components/MyButton.vue'
export default {
components: {
MyButton
},
methods: {
onButtonClick() {
alert('Привет!')
}
}
}
</script>
|
2. Жизненный цикл компонента
Хуки жизненного цикла
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <script>
export default {
created() {
console.log('Компонент создан')
},
mounted() {
console.log('Компонент смонтирован')
},
updated() {
console.log('Компонент обновлен')
},
unmounted() {
console.log('Компонент размонтирован')
}
}
</script>
|
Директивы
1. Встроенные директивы
v-bind и v-on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| <template>
<div>
<img :src="imageUrl" :alt="imageAlt">
<button @click="handleClick">
Нажми меня
</button>
</div>
</template>
<script>
export default {
data() {
return {
imageUrl: '/images/logo.png',
imageAlt: 'Логотип'
}
},
methods: {
handleClick() {
console.log('Кнопка нажата')
}
}
}
</script>
|
2. Условные директивы
v-if и v-show
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| <template>
<div>
<p v-if="isLoggedIn">
Добро пожаловать, !
</p>
<p v-else>
Пожалуйста, войдите
</p>
<div v-show="isVisible">
Этот элемент можно скрыть
</div>
</div>
</template>
<script>
export default {
data() {
return {
isLoggedIn: true,
username: 'John',
isVisible: true
}
}
}
</script>
|
Управление состоянием
1. Vuex
Настройка хранилища
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0,
user: null
},
mutations: {
increment(state) {
state.count++
},
setUser(state, user) {
state.user = user
}
},
actions: {
async fetchUser({ commit }) {
const user = await api.getUser()
commit('setUser', user)
}
},
getters: {
isLoggedIn: state => !!state.user
}
})
|
Использование в компоненте
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| <template>
<div>
<p>Счет: 9</p>
<button @click="increment">
Увеличить
</button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
...mapMutations(['increment'])
}
}
</script>
|
2. Composition API
Использование setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| <template>
<div>
<p>Счет: 9</p>
<button @click="increment">
Увеличить
</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
</script>
|
Маршрутизация
1. Vue Router
Настройка маршрутов
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
export default createRouter({
history: createWebHistory(),
routes
})
|
Использование в приложении
1
2
3
4
5
6
7
8
9
10
| <template>
<div>
<nav>
<router-link to="/">Главная</router-link>
<router-link to="/about">О нас</router-link>
</nav>
<router-view></router-view>
</div>
</template>
|
Оптимизация
1. Ленивая загрузка
Асинхронные компоненты
1
2
3
4
5
6
7
| <script>
export default {
components: {
HeavyComponent: () => import('./HeavyComponent.vue')
}
}
</script>
|
2. Кэширование
Keep-alive
1
2
3
4
5
| <template>
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
</template>
|
Тестирование
1. Jest и Vue Test Utils
Написание тестов
1
2
3
4
5
6
7
8
9
10
| import { mount } from '@vue/test-utils'
import Counter from './Counter.vue'
test('увеличивает счетчик при клике', async () => {
const wrapper = mount(Counter)
await wrapper.find('button').trigger('click')
expect(wrapper.find('p').text()).toBe('Счет: 1')
})
|
2. E2E тестирование
Cypress
1
2
3
4
5
6
7
| describe('Counter', () => {
it('увеличивает счетчик при клике', () => {
cy.visit('/')
cy.get('button').click()
cy.get('p').should('contain', 'Счет: 1')
})
})
|
Заключение
Vue.js - это мощный и гибкий фреймворк для создания современных веб-приложений. Понимание основ Vue.js и правильное использование его возможностей поможет создавать качественные и масштабируемые приложения.