Доступ к компонентам Ractive из их родителя

Я оказался в ситуации, когда я хотел бы получить доступ к экземплярам, ​​созданным из компонента Ractive, из родительского Ractive. Например.

var myComponent = Ractive.extend(
    {
        uselessFunction: function()
        {
            alert('Hello ' + this.data.who);
        }
    }
);

var myRactive = new Ractive(
    {
        el: 'body',
        components:
        {
            mycomponent: myComponent
        },
        template: '{{#people}}<rv-mycomponent who="{{.}}"/>{{/people}}',
        data:
        {
            people:
            [
                'Mike',
                'Charly',
                'April'
            ]
        }
    }
);

Запустив это, я получу 3 экземпляра myComponent. Теперь я хотел бы иметь какой-то способ вызвать бесполезную функцию для любого экземпляра компонента из метода myRactive (или даже лучше для всех экземпляров).

Конечно, есть много возможных обходных путей (например, использование наблюдателей в компонентах, а затем изменение некоторого общего свойства) для достижения этой цели, но я надеялся на какой-то встроенный интерфейс. Увы, сколько бы я ни просеивал myRactive Object, я не могу найти ссылку на экземпляры компонентов. Хотя я подозреваю, что он есть, поскольку метод teardown() myComponent также вызывает метод teardown() для каждого компонента.


person skeptic35    schedule 27.11.2013    source источник


Ответы (3)


Обновление: этот ответ очень старый. Правильный способ доступа к дочерним компонентам – ractive.findComponent(name) или ractive.findAllComponents(name).


Не существует хорошего способа сделать это, но это возможно:

people = [];

Ractive.components.person = Ractive.extend({
  init: function () {
    people.push( this );
  },
  uselessFunction: function () {
    alert( 'Hello ' + this.get('who') );
  }
};

ractive = new Ractive({
  el: 'body',
  template: '{{#people}}<person who="{{.}}"/>{{/people}}',
  data: { people: [ 'Mike', 'Charly', 'April' ] }
};

// later...
people[0].uselessFunction(); // alerts 'Hello Mike'

(примечание: этот код не будет работать с текущей версией, предполагается, что вы используете 0.3.8, которая исключает rv- и позволяет вам глобально регистрировать компоненты на Ractive.components.)

Как я уже сказал, это довольно неэлегантно. Пытались найти лучший способ решить эту проблему. Один из подходов, который я изучаю, состоит в том, чтобы разрешить ractive.find() и ractive.findAll(), которые аналогичны ractive.el.querySelector()/ractive.el.querySelectorAll(), находить компоненты (например, ractive.findAll('people')), а также узлы DOM. Я открыт для любых предложений в то же время!

person Rich Harris    schedule 27.11.2013
comment
Глобальное пространство имен не подходит, так как я работаю с настройкой AMD. Но на данный момент я использую довольно похожий обходной путь, когда я передаю объект компонентам, которые вводят экземпляры. Однако поиск обходных путей не моя проблема;). Разве нельзя просто иметь свойство в ractive объекте (например, «подкомпоненты» или что-то еще), которое содержит ссылки на экземпляры компонентов? - person skeptic35; 28.11.2013
comment
Я вижу, что экземпляр компонента содержит ссылку на родителя в .component.parentFragment.root, поэтому теоретически я мог бы использовать это для внедрения ссылки на мой компонент в родителя. Увы, свойство .component пока недоступно при вызове любой из callback-функций (beforeInit, complete, init). - person skeptic35; 28.11.2013
comment
Похоже, каждый компонент должен знать о своих дочерних элементах. Я не могу вспомнить ни одного фреймворка, который не использовал, по крайней мере, не на рабочем столе. - person Joel; 24.12.2013
comment
@skeptic35 В последней версии для разработчиков (0.3.9-pre) компоненты имеют ссылку this._parent, которая используется внутри. У него есть ведущее подчеркивание, потому что я не думаю, что это хорошая практика, когда компонент может возиться со своим родителем (делает его менее пригодным для повторного использования и т. д.), поэтому это не «правильная» часть API - но в равной степени я этого не делал не вижу смысла скрывать это от пользователей библиотеки. - person Rich Harris; 24.12.2013
comment
@Joel Джоэл - Да, ты напомнил мне, что для этого нужна проблема с GitHub. Вуаля! Спасибо за подсказку - person Rich Harris; 24.12.2013
comment
@RichHarris Может быть, обновить этот ответ на комментарий к проблеме, упомянутой в упомянутой выше проблеме? github.com/ractivejs/ractive/issues/1556#issuecomment-66140561 - person mikemaccana; 17.11.2016
comment
@mikemaccana, хорошее место, я обновил ответ на «использовать ractive.findComponent». - person Rich Harris; 17.11.2016

Похоже, .findComponent() теперь это делается сейчас:

ractiveInstance.findComponent( name )
person mikemaccana    schedule 17.11.2016

Вот похожее решение, которое я использую:

Ractive.defaults.isolated=true;
componentsHash = {};  // GLOBAL
Ractive.defaults.oninit=function(){
    if (this.get('ref'))
        componentsHash[this.get('ref')]=this;
};
Ractive.defaults.onteardown=function(){
    if (this.get('ref') && componentsHash[this.get('ref')])
        delete(componentsHash[this.get('ref')]);
};

Объект "componentsHash" содержит ссылку на все созданные компоненты.

Использование:

<some-component ref="Mike1"/>
<some-component ref="Mike2"/>

Затем вы можете найти экземпляр компонента Mike1, используя:

componentsHash['Mike1']
person Igor Vujovic    schedule 09.06.2016