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
   }
}

что делает этот фрагмент кода?

  1. Он создает свойство с именем val для компонента (в прототипе, чтобы <vueInstanece>.hasOwnProperty('val') показывал false).

  2. У него есть дерево зависимостей, которое состоит из реактивных свойств (свойств данных, других вычисляемых свойств) в этом случае: this.someDataProperty, что означает, что в момент изменения зависимостей вычисленное свойство будет пересчитано.

  3. Несмотря на дискуссию, аргументы не могут быть переданы. Так что-то вроде

    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)
   }
}
  1. Он не создает никакого нового свойства, но отслеживает изменения реактивного свойства.

  2. Следит только за одним конкретным свойством, в отличие от вычисленного, когда любое изменение зависимого свойства может вызвать пересчет.

  3. Имеет аргументы нового и старого значения.


Таким образом, вычисленные свойства будут подходить, если:

Вы хотите свойство, которое всегда зависит от других свойств. Как форматирование текста для шаблона, который даже является примером в вашем коде.

Или уменьшая переменную длину, так как это довольно часто встречается:

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

смотреть

Используйте часы, когда вы хотите выполнять асинхронные или дорогие операции в ответ на изменение данных.

вычисленных

Использование вычисляется в других случаях. Вычисляемые свойства кэшируются на основе их зависимостей. В основном используется, когда вы хотите только переоценить некоторые из его зависимостей, изменились.