Как отследить вложенный атрибут в компоненте Glimmer? - PullRequest
1 голос
/ 20 января 2020

Я создаю свой первый компонент Glimmmer в Ember, и у меня в шаблоне было что-то вроде этого:

<p>Some val: {{this.my_obj.some.deeply.nested.path.to.val}}</p>

Затем я создал соответствующий файл компонента .js и подумал, что попытаюсь удалить длинный путь от HTML.

Моя первая попытка была сделать геттер:

get val() {
  return this.my_obj.some.deeply.nested.path.to.val;
}

С шаблоном сейчас:

<p>Some val: {{this.val}}</p>

Это работает изначально и отображает начальное значение, присвоенное переменной val, но оно не обновляется при изменении базового val.

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

@tracked val;

get val() {
  return this.my_obj.some.deeply.nested.path.to.val;
}

Затем я попробовал это, но это неверный синтаксис:

@tracked this.my_obj.some.deeply.nested.path.to.val;

Так как же это обрабатывать в компоненте Glimmer?

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

Ответы [ 2 ]

2 голосов
/ 20 января 2020

Все просто: все, что вы меняете, должно быть @tracked. Если у вас есть {{this.my_obj.some.deeply.nested.path.to.val}} в вашем hbs или получателе, который возвращает, который не имеет значения.

Но если вы делаете this.my_obj.some.deeply.nested.path.to.val = "something" и хотите, чтобы значение обновлялось, вам нужно убедиться, что при this.my_obj.some.deeply.nested.path.to val определяется как отслеживаемое.

Так что это не сработает:

@tracked data;
constrcutor() {
  super(...arguments);
  this.data = { foo: 1 };
}
@action test() {
  this.data.foo = 2; // this will not correctly update
}

вам необходимо убедиться, что foo равно @tracked:

class DataWrapper {
  @tracked foo;
}

...

@tracked data;
constrcutor() {
  super(...arguments);
  this.data = new DataWrapper();
  this.data.foo = 1;
}
@action test() {
  this.data.foo = 2; // this will now correctly update
}

Или вы сделали недействительным вручную. Так что это будет работать:

@tracked data;
constrcutor() {
  super(...arguments);
  this.data = { foo: 1 };
}
@action test() {
  this.data.foo = 2; // this will not update
  this.data = this.data; // this ensures that everything that depends on `data` will correctly update. So `foo` will correctly update.
}

Также важная вещь: @tracked никогда не должно быть определено в геттере. Так не пойдет. Это должно быть непосредственно определено, где вы хотите изменить что-то, что должно вызвать обновление Однако вы можете использовать геттеры без проблем. Это будет работать, пока все, что вы установили с помощью objsomething = value, будет правильно @tracked. Также (чисто) вызовы функций будут просто работать.

0 голосов
/ 20 января 2020

Я нашел ответ в этой таблице - https://ember-learn.github.io/ember-octane-vs-classic-cheat-sheet/#component -properties

Существует декоратор @computed, который позволяет правильно отслеживать вложенный атрибут на предмет изменений:

import { computed } from '@ember/object';

// Note that no 'this.' is used here
@computed("my_obj.some.deeply.nested.path.to.val")
get val() {
  return this.my_obj.some.deeply.nested.path.to.val;
}
...