VueJs, разница между вычисленным свойством и наблюдателем?
В документации Vue.js приведен пример:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
Вышеприведенный код является обязательным и повторяющимся. Сравните его с вычисленной версией свойства:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
Каковы ситуации, когда наблюдатели более подходят, чем рассчитанные свойства? Как я должен решить, что выбрать? Документация продолжает говорить, что она более "родовая", но на самом деле не ставит своей цели.
Ответы
Ответ 1
Вычисленные свойства
Пример вычисляемого свойства:
computed: {
val () {
return this.someDataProperty * someOtherVariable
}
}
что делает этот фрагмент кода?
Он создает свойство с именем val
для компонента (в прототипе, чтобы <vueInstanece>.hasOwnProperty('val')
показывал false
).
У него есть дерево зависимостей, которое состоит из реактивных свойств (свойств данных, других вычисляемых свойств) в этом случае: this.someDataProperty
, что означает, что в момент изменения зависимостей вычисленное свойство будет пересчитано.
Несмотря на дискуссию, аргументы не могут быть переданы. Так что-то вроде
computed: {
val (flag) {
return (flag === 1)
? this.someDataProperty * someOtherVariable
: this.someDataProperty * 5
}
}
нельзя сделать
[РЕДАКТИРОВАТЬ] См.: https://vuejs.org/v2/guide/computed.html#Computed-Setter
Watcher
Образец наблюдателя:
watch: {
val (n, o) {
console.log(n, o)
}
}
Он не создает никакого нового свойства, но отслеживает изменения реактивного свойства.
Следит только за одним конкретным свойством, в отличие от вычисленного, когда любое изменение зависимого свойства может вызвать пересчет.
Имеет аргументы нового и старого значения.
Таким образом, вычисленные свойства будут подходить, если:
Вы хотите свойство, которое всегда зависит от других свойств. Как форматирование текста для шаблона, который даже является примером в вашем коде.
Или уменьшая переменную длину, так как это довольно часто встречается:
this.$store.state.someProperty.someNestedProperty.someDeeplyNestedProperty
можно уменьшить до:
computed: {
someDeeplyNestedProperty () {
return this.$store.state.someProperty.someNestedProperty.someDeeplyNestedProperty
}
}
Не только уменьшение размера переменной, каждый раз, когда магазин обновляется, вы получите последнее значение в someDeeplyNestedProperty
.
И Наблюдатели полезны, если вы хотите узнать, изменилось ли одно реактивное свойство на подходящее значение, чтобы знать, что вы готовы выполнить действие.
как:
watch: {
somethingSelected() {
this.router.push('someOtherRoute')
}
}
РЕДАКТИРОВАТЬ: я натолкнулся на хорошую статью Флавио Копеса, в которой перечислены общие случаи использования каждого из них (методы, вычисляемые реквизиты, наблюдатели):
Когда использовать методы
Чтобы реагировать на события, происходящие в DOM
Для вызова функции, когда что-то происходит в вашем компоненте. Вы можете вызывать методы из вычисляемых свойств или наблюдателей.
Когда использовать вычисляемые свойства
- Вам необходимо составить новые данные из существующих источников данных
- У вас есть переменная, которую вы используете в своем шаблоне, которая построена из одного или нескольких свойств данных
- Вы хотите уменьшить сложное имя вложенного свойства до более удобочитаемого и удобного в использовании, но обновить его при изменении исходного свойства
- Вам нужно сослаться на значение из шаблона. В этом случае лучше всего создать вычисляемое свойство, поскольку оно кэшируется.
- Вам необходимо прослушать изменения более чем одного свойства данных
Когда использовать наблюдателей
- Вы хотите слушать, когда изменяется свойство данных, и выполнять какие-то действия
- Вы хотите прослушать изменение значения пропа
- Вам нужно только прослушать одно конкретное свойство (вы не можете одновременно просматривать несколько свойств)
- Вы хотите наблюдать свойство данных, пока оно не достигнет определенного значения, а затем сделать что-то
Ответ 2
Вычислимые свойства имеют очень специфическую цель: составление новых данных, полученных из других данных. Они используются всякий раз, когда у вас есть данные, и их нужно преобразовать, фильтровать или иным образом манипулировать им, прежде чем использовать его в шаблоне.
Вычислимые свойства всегда должны возвращать значение, не должны иметь никаких побочных эффектов, и они должны быть синхронными.
Таким образом, существует довольно много ситуаций, когда вычисляемые свойства вам не помогут, например: ваш компонент получает опору, и всякий раз, когда сменяет prop, ваш компонент должен был выполнить запрос ajax. Для этого вам нужен наблюдатель.
Наблюдатели не полезны так часто, как вычисленные свойства, поэтому вы всегда должны думать о том, может ли вычисленное свойство решить вашу проблему, и только откидываться на наблюдателя (или иногда на метод), если это не так.
Ответ 3
Vue.js реагирует
Это означает, что он способен реагировать на такие вещи, как ввод данных пользователем и изменение данных. Я рекомендую ознакомиться с системой реактивности, чтобы лучше понять механизм, который Vue использует под капотом, когда наблюдается изменение данных. Есть три основных способа, чтобы ваши компоненты использовали реактивный характер Vues. Это Методы, Вычисленные Свойства и Наблюдатели. Без тщательного изучения эти параметры могут показаться взаимозаменяемыми (и в некоторых отношениях они есть), но каждый из них имеет свой сценарий наилучшего варианта использования. Чтобы проиллюстрировать примеры, я создам небольшое приложение для оценки, которое позволяет учителю вводить результаты тестов для учащихся в их классе, просматривать среднюю оценку и настраивать леса для функции автосохранения.
МЕТОДЫ
TL; DR - Используйте методы, когда вы хотите изменить состояние компонентов или когда произошло событие, которое не обязательно связано с изменением данных экземпляра. Методы могут принимать аргументы, но не отслеживают никаких зависимостей. Когда вы используете метод, он обычно создает некоторый побочный эффект внутри компонента, и методы запускаются при каждой перезагрузке компонента. Это означает, что если пользовательский интерфейс обновляется очень часто, этот метод (и любые другие методы компонента) также будут работать. Это может вызвать проблемы с производительностью или отставание в пользовательском интерфейсе.
Ниже приведено начало нашего оценочного приложения. Там нет проверки или что-то еще, и это не красиво, я знаю. У нас есть небольшой набор тестов в нашем объекте данных (имя студента и оценка). И метод, который мы можем использовать для добавления другого тестового объекта в тесты нашего свойства данных.
new Vue({
el: "#app",
data: {
newTest: {
studentName: '',
score: 0
},
tests: [{
studentName: "Billy",
score: 76
}, {
studentName: "Suzy",
score: 85
}, {
studentName: "Johnny",
score: 89
}, {
studentName: "Emma",
score: 93
}]
},
methods: {
addTestScore: function() {
this.tests.push({
studentName: this.newTest.studentName,
score: this.newTest.score
});
this.newTest.studentName = '';
this.newTest.score = 0;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<body>
<div id="app">
<ul>
<li v-for="test in tests">
{{test.studentName}} - {{test.score}}
</li>
</ul>
<span>Student</span>
<input v-model="newTest.studentName">
<span>Score</span>
<input v-model="newTest.score">
<button @click="addTestScore">Add </button>
</div>
</body>
Ответ 4
Для целей этого примера вычисленные свойства действительно лучше. В примере, который использует наблюдатели, обратите внимание, что эта строка кода:
this.fullName = this.firstName + ' ' + val
очень похож на это:
this.fullName = val + ' ' + this.lastName
Оба выполняют одну и ту же цель, наблюдая за изменениями в первом или последнем имени и обновляя fullName
соответственно. Но так как это никогда не изменится, и fullName
всегда будет состоять из firstName
и lastName
, тогда мы сможем избежать суеты и создать вычисленное свойство. Затем каждый раз, когда firstName
и lastName
меняются, fullName
будет обновляться автоматически.
В некоторых случаях лучше использовать наблюдателей. Если вы хотите сделать некоторые серьезные вычисления для написания некоторого асинхронного кода, тогда наблюдатель может быть более подходящим.
Например, если у вас есть что-то вроде следующего:
let app = new Vue({
el: '#app',
data: {
name: ""
}
});
И вы хотите, чтобы каждый раз, когда name
менялся, чтобы сделать с ним вызов API, получить результат и обработать его, тогда более подходящий наблюдатель:
watchers: {
"name": function(newValue, oldValue){
if(newValue != oldValue)} {
fetch(url, {method: 'post', body: JSON.stringify({name: this.name})}).then(...);
}
}
}
Чтобы сделать это с вычисленным свойством, вам необходимо реализовать свойство computed get()
и computed set()
, которое приведет к большему количеству кода.
Также обратите внимание, что в примере документации у нас есть свойство fullName
, которое составлено a.k.a вычислено двумя другими свойствами. В моем примере name
не вычисляется, в буквальном смысле этого слова. Мы просто хотим это наблюдать, поэтому использование вычисленного свойства будет скорее хаком, чем шаблоном проектирования.
Ответ 5
Вы используете наблюдателя, когда хотите изменить значение или выполнить действие, основанное на изменении другого значения. Хорошим примером этого является установление значения на основе пропеллера и вы хотите реагировать на любые изменения:
Vue.component('my-comp',{
template: '#my-comp',
props: ['username'],
created() {
this.user = this.username;
},
watch:{
username(val){
this.user = val;
}
},
data(){
return{
user: ''
}
}
});
См. этот JSFiddle: https://jsfiddle.net/fjdjq7a8/
Этот пример немного надуман и не работает в реальном мире, потому что мы не синхронизируем значения, поэтому здесь настоящий пример, когда я использую это в одном из проекты с открытым исходным кодом:
Вычисления предназначены для произвольного манипулирования самими данными, поэтому такие вещи, как конкатенация строк и вычисление значений.
Ответ 6
смотреть
Используйте часы, когда вы хотите выполнять асинхронные или дорогие операции в ответ на изменение данных.
вычисленных
Использование вычисляется в других случаях. Вычисляемые свойства кэшируются на основе их зависимостей. В основном используется, когда вы хотите только переоценить некоторые из его зависимостей, изменились.