Функция knockoutjs afterRender в привязке foreach

Я пытаюсь указать входной эффект на вставленные элементы, используя привязку knockoutjs foreach. Очень простая настройка:

myViewModel.myObservableArray.push({enter:function() { ... });

и в разметке:

foreach:{data:myObservableArray, afterRender:enter}

похоже, что он должен работать... правильно? Но он не находит функцию ввода в элементе. То, что я нашел, работает:

myViewModel.enter = function(something, item) { item.enter(); };

foreach:{data:myObservableArray, afterRender:$root.enter}

добавление функции ввода в модель корневого представления и привязка afterRender к $root.enter. Затем Enter передает элемент как свой второй параметр, поэтому он может в свою очередь вызвать функцию ввода элемента, но он чувствует себя как взлома.

Может ли кто-нибудь объяснить, что здесь происходит?

Спасибо.

EDIT:

Чтобы уточнить, я создал fiddle.

Это очень просто и более подробно описано в анимированном переходе. Он запускает функцию в модели корневого представления для каждого элемента dom, который вставлен с использованием привязки foreach.

Итак, вопрос в том, что, если мне нужны функции itemRender, afterAd или beforeRemove? Я мог видеть, что это полезно. Особенно, если использовать привязку шаблона для динамического выбора шаблона (примечание 4). Есть ли чистый способ сделать это? Прямо сейчас у меня есть функция enter в корне модели представления, которая просто вызывает функцию enter на элементе, но, как я уже сказал выше, это похоже на взлом.

Ответ 1

Нет, это способ он был разработан.

Из Documenation:

Примечание 3: Использование "afterRender", "afterAdd" и "beforeRemove"

Иногда вам может потребоваться запустить пользовательскую логику пост-обработки на элементах DOM, сгенерированных вашими шаблонами. Например, если вы используете библиотеку виджетов JavaScript, такую ​​как пользовательский интерфейс jQuery, вы можете перехватить выходные данные шаблонов, чтобы вы могли запускать на нем команды jQuery UI, чтобы преобразовать некоторые из визуализированных элементов в сборщики дат, слайдеры или что-то еще.

Как правило, лучший способ выполнить такую ​​пост-обработку на элементах DOM - это написать пользовательскую привязку, но если вы действительно просто хотите доступ к необработанным элементам DOM, испускаемым шаблоном, вы можете использовать afterRender.

Передайте ссылку на функцию (либо литерал функции, либо укажите имя функции в вашей модели представления), а нокаут вызовет ее сразу после рендеринга или повторного рендеринга вашего шаблона.

(Акцент мой)


Как говорится, пользовательская привязка - это еще один способ сделать это, и может быть лучше в зависимости от того, что делает эта функция enter().

Ответ 2

underscore debounce (_.debounce) - отличное решение в этом случае.

шаблон

data-bind=" template: {foreach:myObservableArray, afterRender: runWhenAllRenderDone }

функция debounce будет выполнена, если afterRender не запущен за последние 100 миллисекунд.

var runWhenAllRenderDone = _.debounce(myFunction, 100);

function myFunction(){
    //do some task but do it for once only
}

is't it awesome?