Использование computed'ов c сеттерами внутри Ember.Component

Опубликовано Пт. 31 Март 2017 в Development

При использовании сеттеров в Ember.Component я сталкнулся с нетрививальным поведеним ember, при передаче параметеров в компонент.

Смотри, например у тебя есть компонент:

import Ember from 'ember';

const {
          computed
      } = Ember;

export default Ember.Component.extend( {
    required: computed( function() {
        alert( 'No overridden!' );
    } ),
    overridden: computed( 'required', {
        get( key ) {
            this.get( '_inner' );
        },
        set( key, value ) {
            this.set( '_inner', `${value}_${this.get( 'required' )}` );
        }
    } ),
    displayValue: computed.alias( 'overridden' )
} );

И вот так ты его используешь:

{{side-effect
  overridden='foo'
  required='bar'}}

Как думаешь, вылетит alert или нет? Можешь проверить себя на ember-twiddle.

А вот для меня было неожиданно, что вылетит.

Причём, если поменять порядок параметров при передаче в компонет, то не вылетит:

{{side-effect
  required='bar'
  overridden='foo'}}

Помнить о порядке для именнованых параметров это так себе идея, поэтому будет радикально рефакторить, а точне полностью избавляться от this.set. Для этого вынесем второй аргумент this.set( ... ) в отдельный Ember.computed:

import Ember from 'ember';

const {
          computed
      } = Ember;

export default Ember.Component.extend( {
    required: computed( function() {
        alert( 'No overridden!' );
    } ),
    displayValue: computed( 'required', 'overridden', function() {
        return `${this.get( 'overridden' )}_${this.get( 'required' )}`;
    } )
} );

И теперь все работает как-надо!

Проверить, если ли у тебя похожий код можно с помощью линтера ember-best-practices, для этого даже отдельное правило есть: no-side-effect-cp

Ну и на будущее - не используй Ember.set в внутри computed, это легко может привести к эксепшену

Яндекс.Метрика