Что касается Ember, я чувствую, что каждый день узнаю что-то новое. Для меня самые большие «ага» моменты возникают во время рефакторинга. Видеть что-то, что «не кажется» правильным, и пытаться выяснить почему, а затем как это исправить. Один из примеров, который постоянно возникает у нас, - это вычисляемые свойства.
Поведение кэширования вычисляемого свойства всегда было для меня немного загадочным. К счастью, обсуждение с Мигелем Камбой помогло мне понять, как они работают, и исправило давно укоренившееся предположение о том, что происходит на самом деле.
Все мы знакомы с тем, как выглядит вычисленное свойство, вот надуманный пример:
name: computed('person.name', function() { return get(person, 'name'); });
Значение вычисляемого свойства кэшируется, и если значение наблюдаемого свойства не изменится, внутренняя функция не будет запускаться каждый раз. В приведенном выше примере это было бы не так уж плохо, но в более крупном примере это ненужная работа для вашего приложения. Важно помнить, что вы всегда должны возвращать значение. Существует много различных типов вычисляемых свойств в зависимости от ваших требований в этом состоянии по умолчанию, когда вы устанавливаете свойство:
set(this, 'name', 'will');
Он переопределит вычисленное свойство ember, которое вы ранее установили, и значение никогда не будет пересчитываться, если отслеживаемый ключ изменится. Вот треп, чтобы продемонстрировать, что я имею в виду.
Вы заметите, что при непосредственной установке вычисляемого свойства значение свойства fullName заменяется новым значением, и значение не будет повторно вычисляться при изменении наблюдаемого ключа. Давайте посмотрим, как мы можем подключиться к способу кэширования вычисляемого свойства и сделать его более явным.
Когда вы определяете вычисляемое свойство, у вас также есть возможность добавить к нему внутренние функции get () и set (). Это даст нам гораздо более точный контроль над кэшированием значений cp. Вы бы написали это так:
name: computed('person.name', { get() { get(this, 'person.name'); }, set(_, value) { return value; }) });
Так что здесь происходит? В каждой из этих внутренних функций мы возвращаем значение для кеширования. При первой проверке этого свойства кеш свойств пуст, поэтому он запускает внутреннюю функцию get () и возвращает имя человека. Тогда это будет кешированное значение, и при последующих получениях будет возвращено первое имя.
Есть два способа изменить кешированное значение.
Первый - сделать недействительным свойство кеша, изменив наблюдаемый ключ (person.first). При следующем доступе к свойству будет запущена внутренняя функция get (), и новое значение в «person.first» будет возвращено и кэшировано.
Второй - set () кешированное значение. Если бы мы сделали следующее:
set(this, 'name', 'Will');
Будет вызвана внутренняя функция set (), у нее есть два аргумента: ключ и значение. Мы можем игнорировать ключ, и все, что нам нужно сделать, это вернуть значение (в данном случае это будет «Will»). Это заменит кешированное значение, и когда вы получите доступ к вычисляемому свойству, будет возвращено значение «Will».
Слово предупреждения здесь: если вы установите один из зависимых ключей в функции set (), это не приведет к аннулированию кеша. Вы также должны всегда возвращать что-то в функции установки, отсутствие возврата будет означать, что «undefined» будет кэшироваться как значение этого свойства.
Для меня это было ключевым моментом, которого мне не хватало в вычисляемых свойствах и этих двух внутренних функциях. Все, что вы делаете, - это возвращаете значение, которое должно быть кэшировано внутри свойства.
Если вы зададите для свойства другое значение, оно будет кэшировано и заменит значение «Will». Если бы вы сделали кеш недействительным, изменив наблюдаемый ключ, функция get () будет запущена, и значение свойства будет пересчитано на основе «person.name», и это значение будет кэшировано.
Взгляните на этот твидл тлеющего угля в качестве примера:
В этом примере у нас также есть кнопка для сброса формы, которая делает недействительным кеш для вычисляемого свойства, что приводит к повторному запуску функции get и возврату начального значения для кеширования.
Это новое понимание вычисляемых свойств действительно упростило способ изменения состояния в наших компонентах и сделало возврат к начальному состоянию компонентов тривиальным. Этот тип функциональности особенно полезен в формах, где вы не хотите, чтобы свойства теней присутствовали в вашем компоненте, и вы хотите легко сбросить состояние, если пользователь отменит.