Подтвердить что ты не робот

Работает ли afterRender с компонентами Knockout?

afterRender работает с привязками к шаблону, но после преобразования моих шаблонов в компоненты, похоже, нет никакого способа использовать afterRender. Я попытался найти пример компонента, который использует afterRender, но ничего не может найти.

4b9b3361

Ответ 1

Я не мог заставить этот метод работать в соответствии с вышеприведенным сообщением. Однако я нашел обходной путь в списке проблем git и не требует специального привязки KO.

Добавьте строку ниже в свой HTML-код компонента или строку кода.

 <span data-bind="template: { afterRender: init }"></span>

Затем создайте функцию init в модуле /viewModel:

 this.init = function() {
   Do cool DOM stuff here.
}

или в зависимости от структуры viewModel:

viewModel: function(params) {
    return {
        init: function () {

        }
    };
},

Работает как шарм. Пример работы здесь

http://jsfiddle.net/gLcfxkv6/1/

Тема на нокауте git здесь: https://github.com/knockout/knockout/issues/1533

Благодаря вампирам на git для обходного пути.

Ответ 2

Секрет здесь http://knockoutjs.com/documentation/custom-bindings.html

ko.bindingHandlers.myCustomBinding = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    // This will be called when the binding is first applied to an element
    // Set up any initial state, event handlers, etc. here
    if (bindingContext.$data.init) bindingContext.$data.init(element, valueAccessor, allBindings, viewModel, bindingContext);
  },
  update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    // This will be called once when the binding is first applied to an element,
    // and again whenever any observables/computeds that are accessed change
    // Update the DOM element based on the supplied values here.
    if (bindingContext.$data.update) bindingContext.$data.update(element, valueAccessor, allBindings, viewModel, bindingContext);
  }
};

поэтому в моем шаблоне компонента я делаю что-то вроде

<div class="row-fluid" data-bind="myCustomBinding: 'someValue'">

и на компоненте viewModel я просто реализую init и/или update, например:

constructor.prototype.init = function(element, valueAccessor, allBindings, viewModel, bindingContext) {
  // All the buttons in the buttons group need the same name,
  // but they all need distinct ids. We use timestamps because
  // as components, the names and ids should be distinct across
  // multiple instances of each component.
  var timeStamp = new Date().getTime();
  $('input:radio').attr('name', timeStamp).button();
  $('input:radio:eq(0)').attr('id', timeStamp+1);
  $('input:radio:eq(1)').attr('id', timeStamp+2);
  $('input:radio:eq(2)').attr('id', timeStamp+3);

  // Initialize the number-picker
  $('input[name="number-picker"]').TouchSpin();
};

Документацию Knockout можно было бы улучшить, указав этот очень полезный случай. Кроме того, это такая полезная привязка, должны быть стандартные привязки для "init" и "update", например

<div data-bind="init: 'someValue'">

Ответ 3

Нам нужно было получить доступ к элементам DOM в компоненте после переключения между различными компонентами. Мы хотели бы использовать несуществующую привязку "afterRender" для компонентов.

Мы решили это с помощью Javascript setTimeout, давая KO сделать его рендеринг в первую очередь, и, в сущности, очередность нашего кода после этого.

HTML:

<div data-bind="component: compName"></div>

Код, переключающий компонент:

var compName = ko.observable();

//...

compName(switchToComponent);
setTimeout(function(){
    // this code is queued until after the component is rendered.
}, 0);