【问题标题】:knockout bind handlers update is not firing for observableArray changes淘汰绑定处理程序更新未针对 observableArray 更改触发
【发布时间】:2016-04-07 19:05:15
【问题描述】:

我正在尝试通过单个绑定处理程序访问多个值,如果在 valuesAccessor 绑定对象内发生 observableArray 更改,绑定处理程序更新不会触发。

ko.bindingHandlers.chosen = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        console.log("INIT");
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
         var value = ko.unwrap(valueAccessor());

         ko.utils.arrayForEach(value,function(binding){            
                var value = ko.unwrap(binding);
        });
        console.log("IT WORKS!");
     }
  };

<select data-bind="
    options: Options,
     chosen: {options: Options}
"></select>

演示:(also on jsFiddle):

    ko.bindingHandlers.chosen = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            console.log("INIT");
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
             var value = ko.unwrap(valueAccessor());
             
             ko.utils.arrayForEach(value,function(binding){            
            		var value = ko.unwrap(binding);
            });
            console.log("IT WORKS!");
        }
    };

    function Model() {

        this.Options = ko.observableArray(opt1);
        this.Reload = function () {
            if (!this.index) {
                this.Options(opt2);
                this.index = 1;
            } else {
                this.Options(opt1);
                this.index = 0;
            }
            this.Options.valueHasMutated();
        };
        this.index = 0;

    }

    var opt1 = [{
        Text: "1",
        Value: "1"
    }, {
        Text: "2",
        Value: "2"
    }, ];
    var opt2 = [{
        Text: "3",
        Value: "3"
    }, {
        Text: "4",
        Value: "4"
    }, ];
    ko.applyBindings(new Model());
<select data-bind="
        options: Options,
        value: Selection,
        optionsText: 'Text',
        optionsValue: 'Value',
        chosen: {options: Options}
    "></select>
<input type="button" data-bind="click: Reload" value="reload" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

【问题讨论】:

  • 告诉我们它意味着做什么,以及你看到它做什么。不要让我们猜测。
  • 另外:如果你能做一个小提琴,9/10 的时间你可以在现场做一个 Stack Snippet(&lt;&gt; 按钮),这是首选。 (两者都很好。)这次我已经为你做了。您的问题之前遗漏了重要代码(问题不能依赖于场外内容)。

标签: javascript jquery html knockout.js knockout-binding-handlers


【解决方案1】:

问题在于您的 chosen 绑定实际上并没有访问可观察数组,因此当它发生变异时,knockout 不会调用您的 update 处理程序,因为它认为它正在使用的任何东西都没有改变。

使用此绑定:

chosen: {options: Options}

您正在绑定一个全新的对象(options 属性指向您的 Options 可观察数组)。这意味着当你这样做时

var value = ko.unwrap(valueAccessor());

value 现在包含:{options: &lt;observableArrayFunction&gt;} - 您需要实际访问其上的options 属性才能敲除注册链接:

ko.utils.arrayForEach(value.options(),function(binding){            

});

如果您进行此更改,您会看到 "IT WORKS!" 现在在更新时被记录下来。它实际上被记录了两次,一次是因为您正在更新数组,另一次是因为您正在调用valueHasMutated

更新了 sn-p(删除了额外的 valueHasMutated):

ko.bindingHandlers.chosen = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            console.log("INIT");
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
             var value = ko.unwrap(valueAccessor());
             
             ko.utils.arrayForEach(value.options(),function(binding){            
            		var value = ko.unwrap(binding);
            });
            console.log("IT WORKS!");
        }
    };

    function Model() {

        this.Options = ko.observableArray(opt1);
        this.Reload = function () {
            if (!this.index) {
                this.Options(opt2);
                this.index = 1;
            } else {
                this.Options(opt1);
                this.index = 0;
            }
        };
        this.index = 0;

    }

    var opt1 = [{
        Text: "1",
        Value: "1"
    }, {
        Text: "2",
        Value: "2"
    }, ];
    var opt2 = [{
        Text: "3",
        Value: "3"
    }, {
        Text: "4",
        Value: "4"
    }, ];
    ko.applyBindings(new Model());
<select data-bind="
        options: Options,
        value: Selection,
        optionsText: 'Text',
        optionsValue: 'Value',
        chosen: {options: Options}
    "></select>
<input type="button" data-bind="click: Reload" value="reload" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    相关资源
    最近更新 更多