【问题标题】:KnockoutJS subscribe to property changes with Mapping PluginKnockoutJS 使用 Mapping Plugin 订阅属性更改
【发布时间】:2012-04-25 23:39:46
【问题描述】:

无论如何我可以告诉淘汰映射插件订阅所有属性更改调用某个函数吗?

我意识到我可以通过这种方式手动订阅属性更改事件:

var viewModel = {
    name: ko.observable('foo'),
}

// subscribe manually here
viewModel.name.subscribe(function(newValue){
   // do work
})

我希望能够进行一般订阅,因为我的视图模型可能会有所不同,我不想硬编码属性名称。我创建了一个执行此操作的函数,但它可能不是最好的方法。它适用于除 IE7 及以下版本之外的所有浏览器。

在这里,我将视图模型作为参数,并尝试通过订阅属性来反映它:

function subscribeToKO(data) {

        $.each(data, function (property, value) {
            if (getType(value) == "Object")
                data[property] = subscribeToKO(value);
            else if (getType(value) == "Array") {
                $.each(value, function (index, item) {
                    item = subscribeToKO(item);
                });
            }
            else {
                if (value.subscribe) {
                    value.subscribe(function (newValue) {
                        // do work                                         
                    });
                }
            }
        });
        return data;
    }

就像我说的那样,这是可行的,但由于我使用的是映射插件,我希望有一个钩子可以用来为它提供一个通常订阅属性更改的函数。

类似:

mapping = {
   create: function(options){
       options.data.subscribe(function(newValue){
            // do work ???
       });
   }
}

ko.mapping.fromJS(viewModel, mapping);

有什么想法吗?

【问题讨论】:

    标签: jquery knockout.js knockout-mapping-plugin


    【解决方案1】:

    这是基于Ryan Niemeyer's dirty flag 的通用方法。
    点击这里查看JsFiddle

    HTML:

    <ol>
    <li>
        Telephone : <input data-bind="value: telephone"/>
    </li>
    <li>
        Address : <input data-bind="value: address"/>
    </li>
    </ol>​
    

    Javascript:

    var model = {
        telephone: ko.observable('0294658963'),
        address: ko.observable('167 New Crest Rd')
    
    };
    // knockout extension for creating a changed flag (similar to Ryan's dirty flag except it resets itself after every change)
    ko.changedFlag = function(root) {
        var result = function() {};
        var initialState = ko.observable(ko.toJSON(root));
    
        result.isChanged = ko.dependentObservable(function() {
            var changed = initialState() !== ko.toJSON(root);
            if (changed) result.reset();
            return changed;
        });
    
        result.reset = function() {
            initialState(ko.toJSON(root));
        };
    
        return result;
    };
    // add changed flag property to the model
    model.changedFlag = new ko.changedFlag(model);
    // subscribe to changes
    model.changedFlag.isChanged.subscribe(function(isChanged) {
        if (isChanged)  alert("model changed");
    });
    ko.applyBindings(model);​
    

    【讨论】:

      【解决方案2】:

      这个方便的小插件与您所做的非常接近,但它提供了多个选项,并且可以满足更广泛的需求,而无需 Mapping 插件:

      https://github.com/ZiadJ/knockoutjs-reactor

      基本上它允许您编写这种代码:

      ko.watch(viewModel, function(target, trigger) { 
          // do work
      });  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-23
        • 2012-08-12
        • 2011-12-07
        相关资源
        最近更新 更多