Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Вычисляемые свойства

Вычисляемое свойство — значение, которое Vue получает из другого состояния и пересчитывает, когда это состояние меняется. Например, число невыполненных задач зависит от списка задач, и хранить его отдельно не нужно.

Функция computed

В этом уроке задачи — объекты с полями id, text и done:

<!-- src/App.vue -->
<script setup>
import { ref, computed } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Купить хлеб', done: true },
  { id: 2, text: 'Позвонить Анне', done: false },
  { id: 3, text: 'Написать отчёт', done: false },
])
 
const remaining = computed(() => {
  return todos.value.filter((todo) => !todo.done).length
})
</script>
 
<template>
  <p>Осталось задач: {{ remaining }}</p>
</template>

На странице появится «Осталось задач: 2». computed принимает функцию, которая возвращает значение, и создаёт объект, похожий на ref: в шаблоне — просто remaining, в скрипте — remaining.value.

Пересчёт

Vue запоминает, какие реактивные данные прочитала функция. Когда они меняются, значение пересчитывается само:

<script setup>
import { ref, computed } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Купить хлеб', done: false },
  { id: 2, text: 'Позвонить Анне', done: false },
])
 
const remaining = computed(() => todos.value.filter((t) => !t.done).length)
 
function finishFirst() {
  todos.value[0].done = true
}
</script>
 
<template>
  <p>Осталось задач: {{ remaining }}</p>
  <button @click="finishFirst">Выполнить первую</button>
</template>

Сначала страница показывает «Осталось задач: 2», после клика — «1».

Отфильтрованный список

Чаще всего computed используют для списков, которые показываются в другом виде:

<script setup>
import { ref, computed } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Купить хлеб', done: true },
  { id: 2, text: 'Позвонить Анне', done: false },
])
const onlyActive = ref(false)
 
const visibleTodos = computed(() => {
  return onlyActive.value
    ? todos.value.filter((t) => !t.done)
    : todos.value
})
</script>

visibleTodos зависит и от списка, и от флага onlyActive. Вывести такой список на страницу поможет директива v-for из урока про списки.

Чем computed лучше функции

Тот же результат даёт функция, вызванная в шаблоне: {{ countRemaining() }}. Разница в кешировании:

Функцияcomputed
Когда выполняетсяПри каждой перерисовкеТолько при изменении зависимостей
Запись в шаблонеcountRemaining()remaining

Если на странице меняется что-то, не связанное с задачами, функция всё равно отработает заново, а computed вернёт сохранённое значение.

Частая ошибка

Менять состояние внутри computed:

<script setup>
const sorted = computed(() => todos.value.sort((a, b) => a.id - b.id))
</script>

Метод sort переставляет элементы исходного массива — функция вычисления меняет данные, от которых сама зависит. Вычисляемое свойство должно только читать и возвращать. Сортируйте копию: [...todos.value].sort(...) или todos.value.toSorted(...).

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.