Как работает computed во Vue 3

Что такое computed

В Vue 3 computed - это функция, которая вычисляет выражение и возвращает результат в виде реактивного значения. Вы можете использовать computed для вычисления нового значения на основе имеющихся реактивных значений и обновления этого значения при изменении зависимостей.

В стиле Composition API

<template>
    <div>
        <p>{{ message }}</p>
        <p>{{ reversedMessage }}</p>
    </div>
</template>

<script>
    import { computed, reactive } from 'vue'

    export default {
        setup() {
            const state = reactive({
                message: 'Hello World'
            })

            const reversedMessage = computed(() => {
                return state.message.split('').reverse().join('')
            })

            return {
                message: state.message,
                reversedMessage
            }
        }
    }
</script>

В этом примере мы имеем объект state с реактивным свойством message. Затем мы используем функцию computed для вычисления значения reversedMessage, которое состоит из обратной строки message.

Выражение () => state.message.split('').reverse().join('') будет пересчитываться при изменении state.message.

В шаблоне мы можем использовать как message, так и reversedMessage. message отображается напрямую из реактивного свойства state.message, а reversedMessage вычисляется на основе state.message.

В стиле Options API

Концепция computed в стиле Options API в Vue предоставляет функциональность для вычисления новых значений на основе реактивных данных и предоставляет их в виде вычисляемых свойств.

Вот пример использования computed в стиле Options API:

<template>
    <div>
        <p>{{ message }}</p>
        <p>{{ reversedMessage }}</p>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                message: 'Hello World'
            }
        },
        computed: {
            reversedMessage() {
                return this.message.split('').reverse().join('')
            }
        }
    }
</script>

В этом примере мы имеем объект data с свойством message. Затем мы используем computed для вычисления значения reversedMessage, которое состоит из обратной строки message. Значение reversedMessage будет пересчитываться при изменении message.

В шаблоне мы можем использовать как message, так и reversedMessage. message отображается напрямую из свойства data.message, а reversedMessage вычисляется на основе data.message.

Кроме того, computed также может иметь дополнительные свойства, такие как get и set, которые позволяют управлять поведением свойства в зависимости от того, является ли оно только для чтения или может быть изменено. Они также предоставляются для того, чтобы вы могли создавать вычисляемые значения на основе других вычисляемых значений.

Зачем get и set в computed свойстве?

В Vue 3, вычисляемые свойства (computed) могут иметь как геттер, так и сеттер. Геттер используется для получения значения свойства, а сеттер - для установки значения.

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

В стиле Composition API

Вот пример использования геттера и сеттера в computed свойстве:

import { computed } from 'vue'

const state = {
    firstName: 'John',
    lastName: 'Doe'
}

const fullName = computed({
    get() {
        return `${state.firstName} ${state.lastName}`
    },
    set(value) {
        const parts = value.split(' ')
        state.firstName = parts[0]
        state.lastName = parts[1]
    }
})

В этом примере мы создаем вычисляемое свойство fullName, которое получает значение из свойств firstName и lastName объекта state. При этом, мы также определяем сеттер, который разбивает строку на две части и устанавливает значения свойств firstName и lastName.

Таким образом, использование геттера и сеттера в computed свойстве позволяет нам более гибко управлять данными, возвращаемыми из свойства, и выполнить дополнительные действия при изменении этих данных.

В стиле Options API

В Options API Vue 3, для создания вычисляемых свойств, можно использовать функцию computed().

export default {
    data() {
        return {
            firstName: 'John',
            lastName: 'Doe'
        }
    },
    computed: {
        fullName: {
            get() {
                return `${this.firstName} ${this.lastName}`
            },
            set(value) {
                const parts = value.split(' ')
                this.firstName = parts[0]
                this.lastName = parts[1]
            }
        }
    }
}

В этом примере мы создаем объект computed, в котором определяем свойство fullName с геттером и сеттером. Геттер возвращает строку, содержащую имя и фамилию, а сеттер разбивает переданную строку на две части и устанавливает соответствующие значения свойств firstName и lastName.

После этого, мы можем использовать свойство fullName в шаблоне компонента или в других методах компонента, как обычное реактивное свойство.

Все равно не понятно как работают set и get?

Хорошо, давайте рассмотрим пример более подробно. Допустим, у нас есть компонент, в котором мы хотим отобразить полное имя пользователя. При этом мы хотим, чтобы пользователь мог изменять свое имя, вводя его в текстовое поле.

Создадим компонент с двумя свойствами - firstName и lastName, а также вычисляемым свойством fullName с геттером и сеттером:

<template>
    <div>
        <label>First Name:</label>
        <input v-model="firstName" />
        <br />
        <label>Last Name:</label>
        <input v-model="lastName" />
        <br />
        <label>Full Name:</label>
        <input v-model="fullName" />
    </div>
</template>

<script>
    export default {
        data() {
            return {
                firstName: 'John',
                lastName: 'Doe'
            }
        },
        computed: {
            fullName: {
                get() {
                    return `${this.firstName} ${this.lastName}`
                },
                set(value) {
                    const parts = value.split(' ')
                    this.firstName = parts[0]
                    this.lastName = parts[1]
                }
            }
        }
    }
</script>

Здесь мы определяем три текстовых поля: для ввода имени, фамилии и полного имени. Для свойства fullName мы определяем геттер, который возвращает строку, содержащую имя и фамилию, а сеттер, который разбивает переданную строку на две части и устанавливает соответствующие значения свойств firstName и lastName.

Теперь, когда мы вводим имя и фамилию в соответствующие текстовые поля, полное имя автоматически отображается в третьем текстовом поле. А если мы вводим полное имя, оно автоматически разбивается на две части, и эти значения устанавливаются в соответствующие свойства.

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

Что если в computed будет несколько реактивных переменных?

Если в computed свойстве в Vue 3 используется несколько реактивных переменных, то при изменении любой из этих переменных будет вызвано пересчитывание вычисляемого свойства.

В стиле Composition API

<template>
    <div>
        <p>{{ firstName }} {{ lastName }}</p>
        <p>{{ fullName }}</p>
    </div>
</template>

<script>
    import { computed, reactive } from 'vue'

    export default {
        setup() {
            const state = reactive({
                firstName: 'John',
                lastName: 'Doe'
            })

            const fullName = computed(() => {
                return `${state.firstName} ${state.lastName}`
            })

            return {
                firstName: state.firstName,
                lastName: state.lastName,
                fullName
            }
        }
    }
</script>

Этот компонент Vue.js использует функцию reactive для создания реактивного объекта state, который содержит свойства firstName и lastName. В функции setup определено вычисляемое свойство fullName, которое объединяет значения свойств firstName и lastName в одну строку.

Наконец, в блоке return возвращаются свойства firstName, lastName и fullName, которые могут использоваться в шаблоне компонента. Компонент экспортируется по умолчанию для использования в других компонентах или приложениях Vue.js.

В стиле Option API

Пример использования computed в стиле Options API с несколькими реактивными переменными:

<template>
    <div>
        <p>{{ firstName }} {{ lastName }}</p>
        <p>{{ fullName }}</p>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                firstName: 'John',
                lastName: 'Doe'
            }
        },
        computed: {
            fullName() {
                return `${this.firstName} ${this.lastName}`
            }
        }
    }
</script>

В этом примере мы имеем объект data с двумя свойствами firstName и lastName. Затем мы используем computed для вычисления значения fullName, которое состоит из конкатенации firstName и lastName. Значение fullName будет пересчитываться при изменении любого из свойств firstName или lastName.

В шаблоне мы можем использовать как firstName и lastName, так и fullName. firstName и lastName отображаются напрямую из свойств data.firstName и data.lastName, а fullName вычисляется на основе этих свойств.

Как понять что это реактивное свойство?

Реактивное свойство в Vue 3 - это свойство, которое было создано с помощью функции reactive или ref. Они позволяют Vue отслеживать изменения этого свойства и автоматически обновлять соответствующие значения в DOM, если это свойство используется в шаблоне.

Создание реактивных свойств в Composition API

Вот пример использования reactive для создания реактивного объекта:

import { reactive } from 'vue'

const state = reactive({
    count: 0
})

В этом примере мы создаем реактивный объект state, который содержит свойство count со значением 0. Теперь, если мы изменим значение count, то Vue автоматически обновит соответствующие значения в DOM.

Вот пример использования ref для создания реактивной переменной:

import { ref } from 'vue'

const count = ref(0)

В этом примере мы создаем реактивную переменную count, которая содержит значение 0. Теперь, если мы изменим значение count, то Vue автоматически обновит соответствующие значения в DOM.

Если вы используете Vue Devtools, то вы можете увидеть, что свойство является реактивным, если оно имеет префикс $, например, $data, $props, $refs, $slots, $emit и другие.

Реактивные свойства в Options API

В Options API Vue 3, для создания реактивных свойств, можно использовать следующие функции:

  • reactive(): создает реактивный объект. Это значит, что все свойства, которые он содержит, также становятся реактивными.
  • ref(): создает реактивную переменную, которую можно использовать для хранения любого значения. Объект ref представляет обертку вокруг значения, которая позволяет отслеживать изменения этого значения.
  • computed(): создает вычисляемое свойство, которое автоматически пересчитывается при изменении его зависимостей.

В Options API Vue 3 также есть реактивные свойства, которые уже есть в компоненте:

  • $data: объект, содержащий все свойства данных компонента.
  • $props: объект, содержащий все свойства, переданные компоненту через атрибуты.
  • $refs: объект, содержащий ссылки на дочерние элементы компонента.
  • $slots: объект, содержащий слоты компонента.
  • $emit: функция для генерации пользовательских событий.

Эти свойства являются реактивными, что означает, что при их изменении Vue автоматически обновляет соответствующие значения в DOM.

Что такое v-model

v-model является директивой во Vue.js, которая используется для создания связи между пользовательским вводом (input) и свойством данных компонента. Она обеспечивает двустороннюю связь между элементом управления и данными, что означает, что любые изменения, внесенные в элемент управления, автоматически отражаются в свойствах данных, и наоборот.

Например в <input v-model="fullName"/>, директива v-model связывает значение ввода элемента <input> с реактивным свойством fullName компонента. Когда пользователь вводит текст в поле ввода, v-model автоматически обновляет значение свойства fullName и наоборот, когда свойство fullName обновляется в компоненте, новое значение автоматически отображается в элементе управления <input>.

В чем основа v-model

Основой директивы v-model в Vue.js является использование событий ввода (input) и обратной связи по принципу "Однонаправленный поток данных".

При использовании директивы v-model, Vue.js автоматически создает привязку между свойством данных компонента и элементом управления (например, <input>, <textarea> или <select>). Это происходит путем прослушивания события ввода на элементе управления и автоматического обновления свойства данных компонента при изменении значения элемента управления.

С другой стороны, когда свойство данных компонента изменяется (например, из-за внутреннего обновления или изменения пользователем), Vue.js автоматически обновляет значение элемента управления, используя связанный атрибут value или выбранный элемент в случае со списками (например, с помощью атрибута selected в теге option).

Таким образом, v-model предоставляет удобный способ для создания двусторонней связи между элементом управления и свойством данных компонента, обеспечивая быстрое и естественное обновление интерфейса приложения в режиме реального времени.

Можно ли аналогично использовать value?

Да, можно использовать атрибут value вместо директивы v-model, чтобы создать привязку между свойством данных компонента и элементом управления в одну сторону. В этом случае, свойство данных компонента будет устанавливаться в соответствии с значением атрибута value элемента управления при его рендеринге.

Однако, при использовании только атрибута value не будет автоматической синхронизации между значением элемента управления и свойством данных компонента, как это делает v-model. При изменении значения элемента управления, необходимо будет вручную обновлять свойство данных компонента, используя обработчик события (например, input или change) на элементе управления.

В целом, использование v-model более удобно и предпочтительно в большинстве случаев, так как это упрощает и ускоряет процесс создания двусторонней связи между элементом управления и свойством данных компонента.

Как понять обработчик на input или change

Обработчик событий на элементе управления input или change нужен для обновления свойства данных компонента, когда пользователь изменяет значение элемента управления.

Когда пользователь взаимодействует с элементом управления (например, текстовым полем <input>, списком выбора <select>, переключателем <radio> или флажком <checkbox>), он генерирует событие. Это событие можно отследить с помощью обработчика событий и выполнить определенный код при его возникновении.

Обработчик событий для input события будет вызываться каждый раз, когда пользователь вводит или изменяет значение элемента управления <input>. Например, если вы хотите обновлять свойство данных fullName каждый раз, когда пользователь вводит новые символы в текстовое поле, вы можете добавить обработчик input события следующим образом:

<template>
    <input type="text" v-bind:value="fullName" v-on:input="updateFullName" />
</template>

<script>
    export default {
        data() {
            return {
                firstName: '',
                lastName: ''
            }
        },

        computed: {
            fullName() {
                return this.firstName + ' ' + this.lastName
            }
        },

        methods: {
            updateFullName(event) {
                const fullName = event.target.value
                const parts = fullName.split(' ')
                this.firstName = parts[0]
                this.lastName = parts.slice(1).join(' ')
            }
        }
    }
</script>

В этом примере, мы связываем значение текстового поля со свойством данных fullName с помощью директивы v-bind:value, а обработчик updateFullName будет вызываться каждый раз, когда пользователь изменяет значение поля. Внутри обработчика, мы извлекаем значение поля из объекта события event, обновляем значения свойств данных firstName и lastName, а затем пересчитываем значение свойства данных fullName с помощью вычисляемого свойства.

Удобство v-model

v-model - это директива во Vue, которая упрощает работу с формами и вводом пользовательских данных. Она позволяет связывать значения элементов управления формы (например, текстовых полей, флажков и т.д.) со свойствами данных компонента в обоих направлениях.

С помощью v-model вам не нужно явно написать обработчики событий для каждого элемента управления формой, чтобы обновлять свойства данных. Вместо этого, вы можете использовать v-model и Vue автоматически сгенерирует соответствующие обработчики для вас.

Например, рассмотрим пример текстового поля, связанного с свойством данных message:

<template>
    <div>
        <input type="text" v-model="message" />
        <p>Сообщение: {{ message }}</p>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                message: ''
            }
        }
    }
</script>

Здесь мы используем v-model для связывания значения текстового поля с свойством данных message. При вводе пользователем значения в поле, Vue автоматически обновит значение свойства данных message. Это работает в обратном направлении: если значение свойства данных message изменится из кода, то значение текстового поля автоматически обновится.

v-model также может использоваться для работы с флажками, радиокнопками и другими элементами формы. Он также позволяет определять свойства и события, связанные с элементом управления, что делает его удобным инструментом для работы с формами во Vue.

Разбор кода

<template>
    <div>
        <label>First Name:</label>
        <input v-model="firstName" />
        <br />
        <label>Last Name:</label>
        <input v-model="lastName" />
        <br />
        <label>Full Name:</label>
        <input v-model="fullName" />
    </div>
</template>

<script>
    export default {
        data() {
            return {
                firstName: 'John',
                lastName: 'Doe'
            }
        },
        computed: {
            fullName: {
                get() {
                    return `${this.firstName} ${this.lastName}`
                },
                set(value) {
                    const parts = value.split(' ')
                    this.firstName = parts[0]
                    this.lastName = parts[1]
                }
            }
        }
    }
</script>

fullName следит сразу за тремя свойствами?

Нет, fullName не следит за тремя свойствами, а зависит только от свойств firstName и lastName.

При изменении любого из этих свойств, fullName будет автоматически пересчитано, так как computed свойства в Vue.js являются реактивными и пересчитываются автоматически при изменении связанных с ними реактивных свойств.

А вот при изменении fullName, происходит обратное преобразование и устанавливаются новые значения для firstName и lastName, используя сеттер fullName.

Как в set(value) прилетает v-model=fullName

Событие изменения значения ввода <input v-model="fullName"/> будет привязано к сеттеру fullName. Когда пользователь вводит новое значение в поле ввода и изменяет fullName, Vue.js вызывает этот сеттер и передает ему новое значение value.

Затем сеттер может использовать это значение, чтобы обновить значения firstName и lastName, если это возможно. В зависимости от реализации, сеттер может также выполнить дополнительную проверку на допустимость нового значения и выполнить некоторые действия, например, обновить отображение какой-то другой части приложения.

Полученные знания и резюме

Прочитав эту статью вы узнали следующее:

  • Что такое реактивные свойства в Vue и как их создавать.
  • Что такое вычисляемые свойства в Vue и как их создавать с помощью computed.
  • Как работает директива v-model и как она упрощает управление состоянием компонента.
  • Как использовать методы set и get в computed свойствах, чтобы иметь возможность обрабатывать изменения свойств.
  • Как использовать опции setup и reactive в Vue 3 для создания реактивных компонентов.
  • Как использовать функции в компонентах Vue, чтобы изменять реактивные свойства.

Мы обсудили различные аспекты Vue 3, такие как computed свойства, реактивность, использование v-model и многие другие.

Так же рассмотрели, как работает computed свойство в Vue 3, как определять реактивные свойства и использовать их, а также узнали о преимуществах использования v-model.

Научились понимать примеры кода в стиле Options API, как работают сеттеры и геттеры в computed свойствах. В результате было получено хорошее понимание основ Vue 3 и некоторых из их ключевых функций, что позволит более эффективно работать с этим фреймворком.

Написать комментарий