Теперь Vue.js стал популярным фреймворком для фронтенд-разработки. Многие инженеры используют удобство и мощные возможности Vue.js. Тем не менее, некоторые из принятых нами решений могут не соответствовать лучшим практикам. Что ж, давайте взглянем на эти обязательные к использованию техники Vue.
(Посетите https://pitayan.com/posts/vue-techniques/, чтобы прочитать исходную статью. Исходный код выделен.)
1. Функциональный компонент
Функциональный компонент не имеет состояния и не имеет lifecycle
или methods
. Таким образом, он не может быть создан
Создать функциональный компонент очень просто. Все, что вам нужно сделать, это добавить свойство functional: true
в SFC или добавить functional
в шаблон. Поскольку он такой же легкий, как функция и не имеет ссылки на экземпляр, производительность рендеринга значительно улучшена.
Функциональный компонент полагается на context
и видоизменяется вместе с данными внутри него.
<template functional> <div class="book"> {{props.book.name}} {{props.book.price}} </div> </template>
<script> Vue.component('book', { functional: true, props: { book: { type: () => ({}), required: true } }, render: function (createElement, context) { return createElement( 'div', { attrs: { class: 'book' } }, [context.props.book] ) } }) </script>
2. Глубокие селекторы
Иногда вам даже нужно использовать CSS-компоненты сторонних разработчиков, которые являются scoped
стилями. Невозможно удалить scope
или открыть новый стиль.
Теперь глубокие селекторы >>>
/deep/
::v-deep
попадают в нужное место для помощи.
<style scoped> >>> .scoped-third-party-class { color: gray; } </style>
<style scoped> /deep/ .scoped-third-party-class { color: gray; } </style>
<style scoped> ::v-deep .scoped-third-party-class { color: gray; } </style>
3. Продвинутый «наблюдатель »
Выполнить немедленно
watch
обработчик срабатывает, когда отслеживаемое свойство мутирует. Но иногда это ожидается сразу после создания компонента.
Да, есть простое решение: вызвать обработчик в хуке created
. Но это не выглядит элегантно и между тем повышает сложность.
Или вы можете добавить свойство immediate
к наблюдателю:
watch: {
value: {
handler: 'printValue',
immediate: true
}
},
methods : {
printValue () {
console.log(this.value)
}
}
Глубокое слушание
Иногда опора наблюдателя - это Object
. Но изменение его свойств не может вызвать обработчик наблюдателя. В этом случае добавление deep: true
к наблюдателю может сделать обнаружимую мутацию его свойств.
Обратите внимание, что deep
может вызвать серьезные проблемы с производительностью, если ваш Object
имеет много слоев. Вместо этого лучше подумать об использовании довольно плоской структуры данных.
data () {
return {
value: {
one: {
two: {
three: 3
}
}
}
}
},
watch: {
value: {
handler: 'printValue',
deep: true
}
},
methods : {
printValue () {
console.log(this.value)
}
}
Несколько обработчиков
На самом деле наблюдателя можно установить как Array
. Поддерживаемые типы: String
| Function
| Object
. Зарегистрированные обработчики наблюдателей будут вызываться один за другим при срабатывании триггера.
watch: {
value: [
'printValue',
function (val, oldVal) {
console.log(val)
},
{
handler: 'printValue',
deep: true
}
]
},
methods : {
printValue () {
console.log(this.value)
}
}
Подписаться на мутацию нескольких переменных
watcher
не может прослушивать несколько переменных, но мы могли бы объединить цели вместе как новую computed
и наблюдать за этой новой «переменной».
computed: {
multipleValues () {
return {
value1: this.value1,
value2: this.value2,
}
}
},
watch: {
multipleValues (val, oldVal) {
console.log(val)
}
}
4. Аргумент события: $ event
$event
- это специальная переменная объекта события. В некоторых сценариях он предоставляет дополнительные дополнительные возможности для сложных функций.
Родные события
В собственных событиях значение совпадает с событием по умолчанию (событие DOM или событие окна).
<template> <input type="text" @input="handleInput('hello', $event)" /> </template>
<script> export default { methods: { handleInput (val, e) { console.log(e.target.value) // hello } } } </script>
Пользовательские события
В настраиваемых событиях значение - это то, что получено из его дочернего компонента.
<!-- Child --> <template> <input type="text" @input="$emit('custom-event', 'hello')" /> </template>
<!-- Parent --> <template> <Child @custom-event="handleCustomevent" /> </template>
<script> export default { methods: { handleCustomevent (value) { console.log(value) // hello } } } </script>
5. Разделение параметров маршрутизатора
Я считаю, что это то, как большинство людей обрабатывают параметры маршрутизатора в компоненте:
export default {
methods: {
getRouteParamsId() {
return this.$route.params.id
}
}
}
Использование $route
внутри компонента создаст сильную связь для определенного URL. Это ограничивало гибкость компонента.
Правильное решение - добавить props
к Router
.
const router = new VueRouter({
routes: [{
path: '/:id',
component: Component,
props: true
}]
})
Таким образом, компонент может получать params
прямо из реквизита.
export default {
props: ['id'],
methods: {
getParamsId() {
return this.id
}
}
}
Кроме того, вы также можете передать функцию, возвращающую props
для целей настройки.
const router = new VueRouter({
routes: [{
path: '/:id',
component: Component,
props: router => ({ id: route.query.id })
}]
})
6. Двусторонняя привязка для пользовательских компонентов
Позволяет настраиваемому компоненту настраивать опору и событие, используемые при использовании с v-моделью. По умолчанию v-модель в компоненте использует значение как опору, а ввод как событие, но некоторые типы ввода, такие как флажки и переключатели, могут захотеть использовать опору значения для другой цели. В таких случаях можно избежать конфликта с помощью параметра модели.
v-model
хорошо известен своей двусторонней привязкой. input
- событие обновления по умолчанию. Значение можно обновить с помощью $emit
. Единственное ограничение заключается в том, что компоненту требуется тег <input>
для связывания с атрибутом value
.
<my-checkbox v-model="val"></my-checkbox>
<template> <input type="checkbox" :value="value" @input="handleInputChange(value)" /> </template>
<script> export default { props: { value: { type: Boolean, default: false } }, methods: { handleInputChange (val) { console.log(val) } } } </script>
Есть еще одно решение двусторонней привязки - модификатор sync
. В отличие от v-model
, он не требует, чтобы ваш компонент имел тег <input>
и привязывал к нему значение. Он только запускает update:<your_prop>
, чтобы изменить опору через систему событий.
<custom-component :value.sync="value" />
7. Крючок для жизненного цикла компонентов
Обычно вы можете прослушивать жизненный цикл дочернего компонента (например, mounted
) следующим образом
<!-- Child --> <script> export default { mounted () { this.$emit('onMounted') } } </script>
<!-- Parent --> <template> <Child @onMounted="handleOnMounted" /> </template>
Есть еще одно простое решение. Вместо этого вы можете использовать @hook:mounted
. Он используется во внутренней системе Vue.
<!-- Parent -->
<template>
<Child @hook:mounted="handleOnMounted" />
</template>
8. API прослушивателя событий
Например, добавление таймера при монтировании страницы, но таймер необходимо очистить при уничтожении. Выглядит хорошо.
Честно говоря, this.timer
имеет смысл только тогда, когда используется в beforeDestroy
для получения идентификатора таймера. Не будучи скупым, но чем меньше реактивных переменных, тем выше производительность.
export default {
data () {
return {
timer: null
}
},
mounted () {
this.timer = setInterval(() => {
console.log(Date.now())
}, 1000)
},
beforeDestroy () {
clearInterval(this.timer)
}
}
Сделайте его доступным только в пределах ловушки жизненного цикла. Использование $once
, чтобы избавиться от ненужного.
export default { mounted () { let timer = null
timer = setInterval(() => { console.log(Date.now()) }, 1000)
this.$once('hook:beforeDestroy', () => { clearInterval(timer) }) } }
9. Установите компоненты программно
В некоторых сценариях гораздо удобнее загружать компонент программно. Например, всплывающее окно или модальное окно можно открыть через глобальный контекст $popup()
или $modal.open()
.
import Vue from 'vue' import Popup from './popup'
const PopupCtor = Vue.extend(Popup)
const PopupIns = new PopupCtr()
PopupIns.$mount()
document.body.append(PopupIns.$el)
Vue.prototype.$popup = Vue.$popup = function () { PopupIns.open() }
Element UI реализовал хорошо структурированный модальный компонент, который позволяет использовать пользовательские API для управления жизненным циклом экземпляра. Теория во многом аналогична той, что я демонстрировал выше.
Это 9 приемов о Vue 2.x. Надеюсь, что благодаря этому искусству вы сможете лучше понять, как использовать фреймворк. Если вы считаете эту статью отличной, поделитесь ею в других социальных сетях.
Спасибо, что прочитали!
"Использованная литература"
- Https://vuejs.org
- Https://www.digitalocean.com/community/tutorials/vuejs-add-v-model-support
- Https://vue-loader.vuejs.org/guide/scoped-css.html#child-component-root-elements
Изначально на pitayan.com