Главная » Статьи » Методы, вычисляемые свойства и наблюдатели в Vue.js

Методы, вычисляемые свойства и наблюдатели в Vue.js

Методы, вычисляемые свойства и наблюдатели в Vue.js

От автора: одна из причин, почему я люблю работать с Vue – это полезные Vue js методы (methods), computed и watchers и их четкое различие. Не поняв все 3 термина, сложно использовать функциональность Vue в полном объеме. Тем не менее, большинство людей, путающихся в этом фреймворке, которых я встречал, как правило, путаются и в различиях этих терминов. Поэтому давайте разбираться.

Если вам нужен быстрый ответ, и у вас нет времени читать всю статью:

Methods: это именно то, что написано. Это функции от объекта – обычно это сам объект Vue или компонент Vue.

Computed: эти свойства могут выглядеть так, будто будут использоваться как метод, но это не так. Изменения в определенном свойстве, которое должно быть реактивным, отслеживаются в Vue через data. Вычисляемые свойства позволяют определять свойства, которые используются точно так же, как data, но также могут содержать пользовательскую логику, которая кэшируется в зависимости от зависимостей. Можете считать вычисляемые свойства другим взглядом на data.

Watchers: позволяют заглянуть в систему реактивности. У нас есть несколько хуков, с помощью которых можно наблюдать за любым свойством, хранимом Vue. Если нам нужно добавить какую-либо функциональность при определенном изменении, можно следить за свойством и применять логику. То есть имя наблюдателя должно совпадать с тем, за чем мы наблюдаем.

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

Методы

Методами вы будете часто пользоваться при работе с Vue. По сути, они так названы, потому что мы снимаем функцию с объекта. Они невероятно полезны для подключения функциональности к директивам для событий или даже для создания небольшой логики, которую можно повторно использовать, как любую другую функцию. Методы можно вызывать внутри других методов. Методы можно вызывать внутри хуков жизненного цикла. Они крайне универсальны.

<code class="language-css"><div id="app"> <button @click="tryme">Try Me</button> <p>{{ message }}</p>
</div>
new Vue({ el: '#app', data() { return { message: null } }, methods: { tryme() { this.message = Date() } }
})

Логику можно выполнять и в директивах (<button @click=»message = Date()»>Try Me</button>). И это хорошо работает для таких маленьких примеров. Однако по мере усложнения приложения чаще всего делают, как мы показали сверху, для разбиения и поддержания читаемости. В Vue есть лимит на логику, которую можно поместить в директиву. Например, можно использовать выражения, но не утверждения.

Вы могли заметить, что у нас есть доступ к этому методу внутри того компонента или Vue объекта. Здесь мы можем вызывать любые данные. У нас это this.message. Вам не нужно вызывать метод так же, как вы вызываете функцию в директиве. Например, @click=”methodName()” необязателен. Если не нужно передавать параметры, можно записать @click=”methodName”. С параметрами запись выглядит так @click=”methodName(param)”.

Использовать директивы для вызова методов еще хорошо тем, что у нас есть модификаторы. Один из очень полезных примеров .prevent. Он запрещает обновление страницы при отправке события:

<form v-on:submit.prevent="onSubmit"></form>

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

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

Несколько хороших примеров (этим применение не ограничивается):

Обновление большого объема информации по мере ввода пользователя (например, фильтрация списка)

Сбор информации из Vuex хранилища

Валидация форм

Визуализация данных, меняющихся в зависимости от того, что пользователю нужно увидеть

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

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

Если бы нам нужно было отфильтровать большой список имен героев на основе введенных данных, это было бы так. Мы сохранили простоту, чтобы вы поняли базовую концепцию. Изначально наш список вставляется в шаблон с помощью names, который хранится в data:

new Vue({ el: '#app', data() { return { names: [ 'Evan You', 'John Lindquist', 'Jen Looper', 'Miriam Suzanne', ... ] } }
})
<div id="app"> <h1>Heroes</h1> <ul> <li v-for="name in names"> {{ name }} </li> </ul>
</div>

Создадим фильтр для этих имен. Начнем с создания ввода с v-model, который изначально будет пустой строкой. Будем его использовать для сопоставления и фильтрации списка. Назовем это свойство findName. Ссылка на него есть как в input, так и в data.

<label for="filtername">Find your hero:</label>
<input v-model="findName" id="filtername" type="text" />
data() { return { findName: '', names: [ 'Evan You', 'John Lindquist', ... ] }
}

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

computed: { filteredNames() { let filter = new RegExp(this.findName, 'i') return this.names.filter(el => el.match(filter)) }
}

Теперь обновим, что мы используем в шаблоне, чтобы вывести из этого:

<ul> <li v-for="name in names"> {{ name }} </li>
</ul>

… это:

<ul> <li v-for="name in filteredNames"> {{ name }} </li>
</ul>

Фильтруется каждое нажатие! Для работы всего этого нам понадобилось всего пара строк кода, а не загрузка доп. Библиотек.

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

Наблюдатели

В Vue хорошая абстракция. А любой, кто какое-то время программировал, обычно скажет вам, что абстракция может мешать. Наступает такой момент, когда вы не можете решить какую-либо задачу. Однако такая ситуация объясняется тем, что Vue предоставляет более глубокий доступ к системе реактивности, которую можно использовать как хуки для наблюдения за изменениями. Это может быть невероятно полезно. Как разработчики приложений, мы в большей степени ответственны за то, что меняется.

Наблюдатели позволяют писать намного более декларативный код. Вы больше не отслеживаете сами все. Vue уже делает это под капотом. Поэтому вы можете получить доступ к изменениям, внесенным в любые свойства, которые отслеживаются, в data, computed и props, например.

Наблюдатели невероятно хорошо подходят для выполнения логики, которая применяется к чему—либо еще при возникновении изменения в свойстве (впервые я услышал это от Chris Fritz, но он сказал, что сам услышал это от еще кого-то). Несложное правило – наблюдатели можно использовать для логики, ссылающейся на само свойство. Но это хороший способ понять их отличие от вычисляемых свойств, где изменение будет ссылаться на свойство, которое мы хотим использовать.

Давайте разберем максимально простой пример, чтобы вы поняли.

new Vue({ el: '#app', data() { return { counter: 0 } }, watch: { counter() { console.log('The counter has changed!') } }
})

Как видно из кода сверху, мы храним counter в data. Мы можем наблюдать за ним, используя name свойства, как name функции. Когда мы ссылаемся на этот counter в watch, мы можем наблюдать любые изменения в этом свойстве.

Изменение состояния с помощью наблюдателей

Если состояние очень похоже, его можно просто менять с помощью наблюдателей. Ниже показан пример графика в Vue, который я написал с нуля. При изменении data наблюдатели будут обновлять график и просто плавно переходить между ними.

Для таких задач хорошо подходит SVG, так как в его основе лежат вычисления.

watch: { selected: function(newValue, oldValue) { var tweenedData = {} var update = function () { let obj = Object.values(tweenedData); obj.pop(); this.targetVal = obj; } var tweenSourceData = { onUpdate: update, onUpdateScope: this } for (let i = 0; i < oldValue.length; i++) { let key = i.toString() tweenedData[key] = oldValue tweenSourceData[key] = newValue } TweenMax.to(tweenedData, 1, tweenSourceData) }
}

Что здесь происходит?

Сперва мы создаем пустой объект, который будет обновляться нашей библиотекой анимации

Далее идет функция update, которая запускается на каждом переходном шаге. Она используется, чтобы толкать data

Далее создается объект для хранения исходных data и указатель функции для обновления событий

Создаем цикл for и превращаем текущий индекс в строку

Пробегаемся в цикле по нашему объекту, но мы сделаем это только для определенного ключа

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

Мы наблюдаем за свойством checked и запускаем разные методы, которые хранят таймлайн анимацию, которая меняет оттенок, насыщенность и другие элементы в зависимости от текущего времени. Как ранее говорилось, изменения протекают в выпадающем списке, но логика применяется везде.

watch: { checked() { let period = this.timeVal.slice(-2), hr = this.timeVal.slice(0, this.timeVal.indexOf(':')); const dayhr = 12, rpos = 115, rneg = -118; if ((period === 'AM' && hr != 12) || (period === 'PM' && hr == 12)) { this.spin(`${rneg - (rneg / dayhr) * hr}`) this.animTime(1 - hr / dayhr, period) } else { this.spin(`${(rpos / dayhr) * hr}`) this.animTime(hr / dayhr, period) } }
},

С наблюдателями связаны и другие интересные моменты. Например, у нас есть доступ как к новым, так и к старым версиям свойства в качестве параметров. Для наблюдения за вложенным объектом можно указать deep. В руководстве еще много полезной информации.

Видите, как наблюдатели полезны для всего, что обновляется. Будь-то поля формы, асинхронные обновления или анимация.

Заключение

Надеюсь, это был полезный разбор того, как использовать все 3 функции, и это ускорит разработку приложений за счет эффективного использования Vue. По статистике 70% времени программисты читают код и 30% времени пишут его. Лично мне нравится. Я могу взглянуть на код, который я никогда раньше не видел, и сразу понять, чего автор хотел добиться различиями в методах, вычисляемых значениях и наблюдателях.

Автор: Sarah Drasner

Источник: https://css-tricks.com/

Редакция: Команда webformyself.