Методы лучше всего использовать в качестве обработчиков событий, происходящих в DOM, в ситуациях, когда вам нужно вызвать функцию или выполнить вызов API.
Все значения, возвращаемые методами, не кэшируются.
Например, вы можете создать действие, обозначенное @click, и сослаться на метод:
<template>
<button @click="getDate">Click me</button>
</template>
<script>
export default {
methods: {
getDate() {
alert(Date.now())
}
}
}
</script>
Этот блок кода будет отображать alert с текущим временем всякий раз, когда пользователь нажимает на кнопку Click me. Не следует использовать методы
для отображения вычисляемых данных, так как возвращаемое значение метода, в отличие от computed, не кэшируются, что может привести к снижению производительности в вашем приложении в случае неправильного использования.
Как уже упоминалось, computed лучше всего использовать при реагировании на обновления данных или для составления сложных выражений в вашем шаблоне. В следующем примере, если данные в animalList изменятся, computed свойство - animals, также будет обновляться, вырезая второй элемент из массива и
возвращает новое значение:
<template>
<div>{{ animals }}</div>
</template>
<script>
export default {
data() {
return {
animalList: ['dog', 'cat']
}
},
computed: {
animals() {
return this.animalList.slice(1)
}
}
}
</script>
Реактивность делает computed свойства идеальными для составления новых переменных из существующих данных, например, когда вы ссылаетесь на конкретные ключи более крупного и сложного объекта.
Вычисляемые свойства также помогают повысить читабельность вашего template компонента и его логики. В следующем примере, мы выводим авторов двумя разными способами, но с вычисляемым свойством authorName вы можете составить условную логику, не раздувая HTML шаблон:
<template>
<div>
<p id="not-optimal">{{ authors[0].bio.name }}</p>
<p id="optimal">{{ authorName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
authors: [
{
bio: {
name: 'John',
title: 'Dr.',
}
}
]
}
},
computed: {
authorName () {
return this.authors ? this.authors[0].bio.name : 'No Name'
}
}
}
</script>
Однако во многих случаях использование computed может быть излишним, например, когда вы хотите наблюдать только за вложенным свойством определенных данных, а не
за всем объектом. Или когда нужно послушать и выполнить действие при любых изменениях свойства данных или определенного ключа свойства, вложенного внутри
объекта свойства данных, а затем выполнить действие. В этом случае следует использовать watch.
<template>
<div>
<button @click="getNewName()">Click to generate name</button>
<p v-if="author">{{ author }}</p>
</div>
</template>
<script>
export default {
data() {
return {
data: {},
author: '',
}
},
watch: {
data: function(newVal, oldVal) {
this.author = newVal.first;
alert('Name changed from ${oldVal.first} to ${newVal.first}')
}
},
methods: {
async getNewName() {
await fetch('https://randomuser.me/api/').then(response =>response.json()).then(data => {
this.data = data.results[0].name
})
},
},
}
</script>
Упражнение
Попробуйте создать приложение, которое будет осуществлять поиск, и использованием methods, computed и watcher:
Решение:
<template>
<div class="container">
<h1>Methods vs watchers vs computed props</h1>
<div class="col">
<input type="text" placeholder="Search with method" v-model="input" @keyup="searchMethod"/>
<ul>
<li v-for="(item, i) in methodFilterList" :key="i">{{ item }}</li>
</ul>
</div>
<div class="col">
<input type="text" placeholder="Search with computed" v-model="input2" />
<ul>
<li v-for="(item, i) in computedList" :key="i">{{ item }}</li>
</ul>
</div>
<div class="col">
<input type="text" placeholder="Search with watcher" v-model="input3" />
<ul>
<li v-for="(item, i) in watchFilterList" :key="i">{{ item }}</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// Shared
frameworkList: [
"Vue",
"React",
"Backbone",
"Ember",
"Knockout",
"jQuery",
"Angular",
],
// Method
input: "",
methodFilterList: [],
// Computed
input2: "",
// Watcher
input3: "",
watchFilterList: [],
};
},
created() {
this.searchMethod();
},
watch: {
input3: {
handler() {
this.watchFilterList = this.frameworkList.filter((item) =>
item.toLowerCase().includes(this.input3.toLowerCase())
);
},
immediate: true,
},
},
computed: {
computedList() {
return this.frameworkList.filter((item) => {
return item.toLowerCase().includes(this.input2.toLowerCase());
});
},
},
methods: {
searchMethod() {
this.methodFilterList = this.frameworkList.filter((item) =>
item.toLowerCase().includes(this.input.toLowerCase()));
},
},
};
</script>
<style scoped>
.container {
margin: 0 auto;
padding: 30px;
max-width: 600px;
font-family: "Avenir", Helvetica, Arial, sans-serif;
}
.col {
width: 33%;
height: 100%;
float: left;
}
input {
padding: 10px 6px;
margin: 20px 10px 10px 0;
}
</style>
В этом упражнении мы увидели, как можно создать отфильтрованный список, используя
methods, computed и watch.
В этом разделе кратко продемонстрированы три подхода. Каждый подход имеет
свои плюсы и минусы и выбор наиболее подходящего подхода для применения зависит от многих факторов.