Вот несколько советов по работе с Vue.js которые я выработал за последний год.
Используйте стрелочные функции в компонентах
ES6 подарил нам новый способ объявления функций с удобным биндингом текущей области видимости. При использовании старого способа, this может ссылаться не на то что вы ожидаете.
Например:
function Person () {
this.age = 0;
setInterval(function growUp () {
// `this.age` здесь равен undefined
// эта функция создает новую область видимости
// отличную от области видимости функции Person
console.log(this.age);
}, 1000)
}
const Developer = new Person();
Функция growUp определила свою область видимости и this внутри нее не ссылается на объект Person. Добиться желаемого поведения, можно сохранив область видимости в переменной, или используя функцию .bind(context)
// Сохраняем контекст в переменной that
function Person () {
var that = this;
that.age = 0;
setInterval(function growUp () {
console.log(that.age);
}, 1000)
}
// или используем функцию bind
function Person () {
this.age = 0;
setInterval(function growUp () {
console.log(this.age);
}.bind(this), 1000)
}
Но самым удобным вариантом будет простое использование стрелочной функции. Она автоматически привязывает область видимости функции к родительской области видимости
function Person () {
this.age = 0;
setInterval(() => {
console.log(this.age);
}, 1000)
}
Так лучше, не правда ли?
Используйте однофайловые компоненты
Однофайловые компоненты (.vue) — одна из моих любимых фич в Vue.js
Они позволяют нам определять многократно используемые шаблоны и отдельные части нашего приложения и переиспользовать их. Но для их использования понадобятся соответствующие инструменты сборки.
(прим. пер. всё это уже настроено и готово к работе в консольной утилите Vue-cli).
Есть два способа создания Vue компонентов.
Например:
Vue.component('my-counter', {
data () {
return {
count: 0
}
},
methods: {
add () {
this.count += 1;
}
},
template: `<div>
<div>{{ count }}</div>
<button @click="add()">Increment</button>
</div>`
}
});
Теперь тоже самое, но используя .vue файл
<template lang="html">
<div>
<div>{{ count }}</div>
<button @click="add()">Increment</button>
</div>
</template>
<script>
export default {
data () {
return {
count: 0
}
},
methods: {
add () {
this.count += 1;
}
}
}
</script>
На небольшом компоненте преимущества не так очевидны, но при установке соответствующих расширений в ваш редактор — вы получите отличную подсветку синтаксиса, а так же вам станет легче найти нужный кусок компонента (сверху вниз идут шаблон, js, стили).
Глобальные плагины
При разработке больших приложений вам вы повсюду будете использовать функциональность одних компонентов внутри других и что бы каждый раз не импортировать .vue компонент внутрь каждого, где нужен его функционал — лучше один раз написать его и использовать как глобальный плагин.
Мы можем сделать один компонент со всей нужной нам функциональностью:
<template lang="html">
<div>
<user-container v-for="u in users">
<p>{{ sayHello(u.name) }}</p>
</user-container>
</div>
</template>
<script>
import UserContainer from './UserContainer' // Придется импортировать в каждый компонент где он нужен
export default {
components: {
UserContainer,
},
methods: {
sayHello (name) {
return `Hello ${name}!`
}
},
computed: {
users () {
return this.$store.getters['users']()
}
}
}
</script>
Или мы можем создать плагин и использовать его:
import UserContainer from './UserContainer'
const Plugin = {
install (Vue, options) {
// <g-user-container> будет доступен глобально во всем приложении
Vue.component('GUserContainer', UserContainer)
Vue.mixin({
computed: {
// `users` так же будет доступен везде
users () {
return this.$store.getters.users
},
}
})
// $sayHello is available within components
Vue.prototype.$sayHello = function (name) {
return `Hello ${name}!`
}
}
}
// И используем наш плагин
import Vue from 'vue'
Vue.use(Plugin)
new Vue({
//...
})
Используйте этот подход, когда видите, что повторяете одинаковый функционал внутри своих компонентов. Don't repeat yourself
Используйте Vuex для хранения состояния
Современные веб-приложения используют большое количество данных на клиенте и управляют ими. Я видел как люди просто хранят все данные внутри компонентов. Это нормальный подход в случае, когда вам не нужен доступ к данным одного компонента из другого.
Очень заманчиво использовать props для передачи данных в компоненты, или использовать библиотеки для подписки на события (Pub—Sub), что бы управлять данными в приложении, но со временем это приводит к раздуванию кода, и становится сложно поддерживать ваше приложение.
Vuex пригодится, когда вашим компонентам понадобиться доступ к одному и тому же состоянию. Вместо того что бы превращать ваш код в ад, прикидывая все данные через props, Vuex позволит хранить в себе всё состояние приложения, и предоставлять к нему доступ нужным компонентам.
С помощью Vuex мы можем определить state (данные), геттеры, экшены и мутации, которые позволят нам манипулировать данными как нам необходимо.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
movies: [],
actors: []
},
getters: {
movies: state => {
return state.movies
},
actors: state => {
return state.actors
}
},
actions: {
getMovies (context) {
axios.get('/api/movies')
.then((movies) => {
context.commit('setMovies', movies)
})
},
getActors (context) {
axios.get('/api/actors')
.then((actors) => {
context.commit('setActors', actors)
})
}
},
mutations: {
setMovies (state, movies) {
state.movies = movies
},
setActors (state, actors) {
state.actors = actors
}
}
})
new Vue({
el: '#app',
store,
render: h => h(App)
})
Используем Vuex внутри компонента:
<template lang="html">
<div>
<div v-for="m in movies">
<p>{{ m.name }}</p>
<p>{{ m.description }}</p>
</div>
<div v-for="a in actors">
<p>{{ a.firstName }} {{ a.lastName }}</p>
</div>
</div>
</template>
<script>
export default {
mounted () {
this.$store.dispatch('getMovies')
this.$store.dispatch('getActors')
},
computed: {
movies () {
this.$store.getters.movies
},
actors () {
this.$store.getters.actors
}
}
}
</script>
Вывод
Vue.js сильно облегчает нам работу, и делает процесс написания новых фич более приятным, но надо потратить немного времени на изучение стека сопутствующих технологий и инструментов.
Надеюсь, вы попробуете Vue.js в своём новом проекте
Комментарии (5)
Waki
01.04.2018 05:30например примеры по созданию плагина и vuex (я не так давно начал изучать vuejs). у меня вопрос по vuex, используя его, любой дочерний компонент может изменять данные напрямую без использования emit?
EvilGenius18
01.04.2018 15:13Да любой компонент может мутировать состояние в vuex:
Компонент:
this.$store.commit('changeValue', true)
Vuex store:
const state = { someProperty: false } const mutations = { changeValue(state, value) { state.someProperty = value } }
А emit используется для отправки изменений в родительский компонентahmpro
01.04.2018 16:45+1Вопрос конечно дискуссионный, но я бы не рекомендовал напрямую вызывать мутации vuex из компонент, сугубо через actions, даже несмотря на то, что на простых кейсах это кажется избыточным.
k12th
Можно истрактовать неверно — будто методы, computed или хуки должны быть стрелочными функциями, хотя на самом деле ровно наоборот.
Используйте стрелочные функции там, где они нужны, а не где-то там:)
На vuex свет клином не сошелся. В небольших приложениях он может показаться громоздким. Есть достаточно альтернатив, например vue-stash.