Погружение в computed setter

Погружение в computed setters

По умолчанию computed данные являются только геттерами, что означает, что они будут выводить только результат вашего выражения.

В некоторых практических сценариях, когда computed свойство изменено, вам может потребоваться активировать внешний API или
изменить исходные данные в другом месте проекта. Функция, которая выполняет это изменение называется setter.

Computed свойство по умолчанию, только возвращает значение, и при попытке задать этому свойству новое значение вы получите ошибку. Но если вы будете использовать setter, то сможете задавать значение computed свойству.

Использование setter в computed свойстве позволяет реактивно прослушивать данные и вызвать функцию (сеттер), который содержит возвращаемое значение из
getter, который можно дополнительно использовать в setter.

Но сначала давайте посмотрим на геттер и сеттер JavaScript ES5. Начиная с ES5, вы можете использовать встроенный геттер и сеттер для определения средств доступа к объектам, таких как:

get свойство Object к функции, которая возвращает значение для этого свойства всякий раз, когда оно
просматривается, как показано здесь:

const obj = {
  get example() {
    return 'Getter'
  }
}
console.log(obj.example) //Getter

set для привязки определенного свойства объекта к функции всякий раз, когда это свойство изменяется:

const obj = {
  set example(value) {
    this.information.push(value)
  },
  information: []
}
obj.example = 'hello'
obj.example = 'world'
console.log(obj.information) //['hello', 'world']

Теперь при задании значения obj.example = 'hello', срабатывает функция.

Основываясь на этих нововведениях, Vue.js предоставляет нам аналогичные функции, get() в качестве геттера и set() в качестве сеттера для конкретного вычисляемого свойства:

computed: {
  myComputedDataProp: {
    get() {}
    set(value) {}
  }
}

Чтобы понять, как работают сеттеры и геттеры, давайте выполним следующие шаги:

Определите возвращаемое значение myComputedDataProp как this.count + 1 всякий раз, когда
myComputedDataProp просматривается:

myComputedDataProp: {
  get() {
    return this.count + 1
  }
},

Затем, всякий раз, когда изменяется myComputedDataProp, используйте setter для установления count нового значения, а затем вызовите метод внутри компонента с именем callAnotherApi с этим новым значением this.count:

myComputedDataProp: {
  set(value) {
    this.count = value - 1
    this.callAnotherApi(this.count)
},

Полный код примера:

data() {
  return {
    count: 0
  }
},
method: {
  callAnotherApi() { //do something }
},
computed: {
  myComputedDataProp: {
    get() {
      return this.count + 1;
    },
    set(value) {
     this.count = value - 1
     this.callAnotherApi(this.count)
    },
  },
 },
}

В данном примере, мы добавили setter, и если вы просто измените count - он станет 1, так как при загрузке сработает сразу геттер, но если вы зададите новое значение самому свойству computed - this.myComputedDataProp = 10, сработает блок кода сеттера.

 

Упражнение

Создадим и импортируем пустой компонент.

Добавим скелет компонента:

<template>
</template>
<script>
  export default {
  }
</script>

Создайте поле ввода с v-model, привязанным к computed свойству - incrementOne, возвращающим значение переменной count в геттере, и устанавливающая переменную count в сеттере:

<template>
  <div class="container">
    <input type="number" v-model="incrementOne" />
    <h3>Get input: {{ incrementOne }}</h3>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        count: -1,
      }
    },
    computed: {
      incrementOne: {
       
       get() {
         // getter
         return this.count + 1;
       },
       set(val) {
         //setter
         this.count = val - 1;
       }     },
   }
</script>

Далее, давайте снова воспользуемся сеттером. Мы разделим новый аргумент val на 2, и сохраните это в новую переменную данных под названием divideByTwo:

<template>
  <div class="container">
    <input type="number" v-model="incrementOne" />
    <h3>Get input: {{ incrementOne }}</h3>
    <h5>Set division: {{ divideByTwo }}</h5>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        count: 0,
        divideByTwo: 0,
      }
   },
//...
</script>

Обновите сеттер, чтобы он делил val на 2, и привяжите это новое значение к переменной DivideByTwo:

set(val) {
  this.count = val
  this.divideByTwo = val / 2
},

Полный код:

<template>
  <div class="container">
    <input type="number" v-model="incrementOne" />
    <h3>Get input: {{ incrementOne }}</h3>
    <h5>Set division: {{ divideByTwo }}</h5>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        count: 0,
        divideByTwo: 0,
      }
    },
    computed: {
      incrementOne: {
       // getter
      get() {
        return this.count
      },
      // setter
      set(val) {
        this.count = val;
        this.divideByTwo = val / 2
      },
    },
  },
 }
</script>

Для запоминания - геттеры используются, когда мы просто получаем значение computed свойства, сеттеры - когда изменяется значение свойства, и мы хотим как то дополнительно обработать значение свойства, как в примере выше - мы получаем в сеттере новое значение, и можем производить какие-то манипуляции на его основе.