Как использовать пользовательские привязки с ko.observableArray()

Как выбить пользовательское связывание с observableArray? При использовании ko.observable () с пользовательской привязкой все работает как положено. При использовании ko.observableArray() генерируются только начальные события (init и update один раз), но дальнейшие изменения не обнаруживаются (см. Fiddle или код ниже).

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="knockout-2.2.1.js"> </script>
</head>
<body>
    <div data-bind="text: Observable, updateBinding: Observable"></div>
    <div data-bind="foreach: ObservableArray, updateBinding: ObservableArray">
        <span data-bind="text: $data"></span>
    </div>
    <script type="text/javascript"> 
        ko.bindingHandlers['updateBinding'] = {
            init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                alert("Binding Handler (Init)");
            },
            update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                alert("Binding Handler (Update)");
            }
        };

        function ViewModel() {
            var self = this;

            self.ObservableArray = ko.observableArray();
            self.Observable = ko.observable();
        }

        var viewModel = new ViewModel();

        // Fires Init + Update for Observable and ObservableArray
        ko.applyBindings(viewModel);

        // Fires Update for Observable
        viewModel.Observable(1);

        // Does nothing
        viewModel.ObservableArray.push('1');
    </script>
</body>
</html>

1 ответ

Решение

Вы захотите создать зависимость от вашего observableArray в вашей пользовательской привязке. Итак, по крайней мере, что-то вроде:

    ko.bindingHandlers.updateBinding = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            alert("Binding Handler (Init)");
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            //create a dependency, normally you would do something with 'data'
            var data = ko.utils.unwrapObservable(valueAccessor());
            alert("Binding Handler (Update)");
        }
    };

Причина того, что это работает с вашим наблюдаемым примером, заключается в том, что все привязки на одном элементе срабатывают вместе (подробнее здесь).

Причиной того, что это не ведет себя так же, как на другой привязке, является то, что foreach ведет себя по-разному. Изменения в observableArray не вызывают foreach связывание напрямую (или весь раздел будет перерисован). Вместо этого он запускает логику в отдельном ko.computed, которое оценивает, как изменился массив, и производит необходимые инкрементные обновления (добавление элемента, удаление элемента и т. Д.).

Другие вопросы по тегам