# Свойства data и методы
# Свойства data
В компоненте свойство data
должно быть функцией. Vue вызывает эту функцию на этапе создания нового экземпляра компонента. Она должна вернуть объект, который затем Vue обернёт в свою систему реактивности и сохранит в экземпляре компонента как $data
. Для удобства, все свойства верхнего уровня объекта доступны через экземпляр компонента:
const app = Vue.createApp({
data() {
return { count: 4 }
}
})
const vm = app.mount('#app')
console.log(vm.$data.count) // => 4
console.log(vm.count) // => 4
// Присвоение значения в vm.count также обновит $data.count
vm.count = 5
console.log(vm.$data.count) // => 5
// ... и наоборот
vm.$data.count = 6
console.log(vm.count) // => 6
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Эти свойства добавляются только при первом создании экземпляра, поэтому убедитесь, что все они присутствуют в объекте, возвращаемом функцией data
. При необходимости используйте null
, undefined
или какое-либо другое значение по умолчанию для свойств, где нужное значение изначально недоступно.
Конечно есть возможность добавления нового свойства в экземпляр компонента без добавления его в data
. Но поскольку этого свойства не было в реактивном объекте $data
, то оно не будет автоматически отслеживаться системой реактивности Vue.
Для обозначения встроенного API, предоставляемого через экземпляр компонента Vue использует префикс $
. Кроме того для внутренних свойств зарезервирован префикс _
. Следует избегать именования свойств data
верхнего уровня, которые начинаются с них.
# Методы
Для добавления методов в экземпляр компонента используется опция methods
. Значением должен быть объект, который будет содержать все необходимые методы:
const app = Vue.createApp({
data() {
return { count: 4 }
},
methods: {
increment() {
// `this` указывает на экземпляр компонента
this.count++
}
}
})
const vm = app.mount('#app')
console.log(vm.count) // => 4
vm.increment()
console.log(vm.count) // => 5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Vue автоматически привязывает значение this
к методам таким образом, чтобы оно указывало на экземпляр компонента. Это гарантирует, что в методе всегда сохраняется правильное значение this
, даже при использовании в качестве обработчика события или коллбэка. Следует избегать использования стрелочных функций при определении methods
, так как это не позволит Vue привязать корректное значение this
.
Как и все остальные свойства экземпляра компонента, methods
доступны в шаблоне компонента. Чаще всего они используются в качестве обработчиков событий:
<button @click="increment">Увеличить счётчик</button>
В примере выше, метод increment
будет вызываться при клике на <button>
.
Метод также можно вызвать непосредственно из шаблона. Как скоро увидим, обычно вместо метода лучше подходит вычисляемое свойство. Но использование метода может быть полезно в некоторых случаях, когда вычисляемые свойства не подходят. Вызвать метод можно в любом месте шаблона, где поддерживаются выражения JavaScript:
<span :title="toTitleDate(date)">
{{ formatDate(date) }}
</span>
2
3
Если методы toTitleDate
или formatDate
обращаются к любым реактивным данным, то они будут отслеживаться как зависимости для отрисовки страницы, как если бы они были непосредственно использованы в шаблоне.
Методы, вызываемые из шаблона, не должны иметь побочных эффектов, таких как изменение данных или запуск асинхронных процессов. Если возникает потребность сделать это, то в этом случае скорее всего лучше подойдёт использование хуков жизненного цикла.
# Реализация debounce и throttle
Vue не предоставляет встроенной поддержки для debounce или throttle, но её легко можно реализовать с помощью сторонних библиотек, например Lodash (opens new window).
Если компонент используется только один раз, можно реализовать debounce в methods
:
<script src="https://unpkg.com/lodash@4.17.20/lodash.min.js"></script>
<script>
Vue.createApp({
methods: {
// debounce с помощью Lodash
click: _.debounce(function() {
// ... обработка клика ...
}, 500)
}
}).mount('#app')
</script>
2
3
4
5
6
7
8
9
10
11
Однако, подобный подход имеет потенциальные проблемы для повторно используемых компонентов, поскольку в таком случае все они получат одну и ту же debounce-функцию. Чтобы сохранить изолированность компонентов друг от друга, можно добавить функцию debounce в жизненном хуке created
:
app.component('save-button', {
created() {
// debounce с помощью Lodash
this.debouncedClick = _.debounce(this.click, 500)
},
unmounted() {
// Остановка таймера при уничтожении компонента
this.debouncedClick.cancel()
},
methods: {
click() {
// ... обработка клика ...
}
},
template: `
<button @click="debouncedClick">
Сохранить
</button>
`
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20