使用带有Knockout.js和Knockout.mapping.js的脏标志或撤消堆栈

时间:2013-10-15 21:29:02

标签: javascript knockout.js knockout-mapping-plugin undo kolite

我正在尝试创建或使用现有的dirtyFlag。然而,我所见过的所有例子都没有讨论如何将它们与knockout.mapping.js插件集成。

有很多很棒的例子,比如Ryan Niemeyer的东西和John Papa的KoLite,但他们都没有回答这个简单的问题

  

"我的viewModel上有很多属性,我没有时间进行手动编码   应该由淘汰映射插件处理的东西"

我觉得这是一个肮脏的(没有双关语意图)需要离开的小秘密。

谢谢!

3 个答案:

答案 0 :(得分:3)

我不是淘汰图书馆的专家,但我是简单解决方案的忠实粉丝。 KoLite中的John Papa和Hans Fjallemarks解决方案:https://github.com/CodeSeven/kolite对于视图模型中所有或选定的可观察对象上的简单但最有效的脏标志是一个很好的解决方案。

我做了一些调整以包含撤消。

ko.DirtyFlag = function (objectToTrack, isInitiallyDirty, hashFunction) {

    hashFunction = hashFunction || ko.toJSON;

    var
        self = this,
        _objectToTrack = objectToTrack,
        _lastCleanState = ko.observable(hashFunction(_objectToTrack)),
        _isInitiallyDirty = ko.observable(isInitiallyDirty),

        result = function () {
            self.forceDirty = function () {
                _isInitiallyDirty(true);
            };

            self.isDirty = ko.computed(function () {
                return _isInitiallyDirty() || hashFunction(_objectToTrack) !== _lastCleanState();
            });

            self.reset = function () {
                _lastCleanState(hashFunction(_objectToTrack));
                _isInitiallyDirty(false);
            };

            self.undo = function () {
                var source = JSON.parse(_lastCleanState());
                for (prop in source) {
                    if (_objectToTrack[prop]() && _objectToTrack[prop]() != source[prop]) {
                        _objectToTrack[prop](source[prop]);
                    }
                }
                _isInitiallyDirty(false);
            };
            return self;
        };

    return result;
};

答案 1 :(得分:1)

  

"我不想用这么多属性手动编写视图模型"

我会在上面添加此评论,但声望限制......

http://knockoutjs.com/documentation/plugins-mapping.html

  

使用“创建”

自定义对象构造      

如果您想自己处理映射的一部分,还可以提供创建回调。如果存在此回调,则映射插件将允许您自己执行映射的这一部分。

var mapping = {
    'children': {
    create: function(options) {
            var newChild = new myChildModel(options.data);
            newChild.dirtyFlag = 'add computed here';
            newChild.changeTracker = 'setup some change tracking or whatever';
            return newChild;
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

因此,当通过映射插件时,使用自定义计算的obervables等扩展来自服务器的数据。

答案 2 :(得分:0)

年轻,我感觉到你的痛苦。我在ko github网站http://jsfiddle.net/b3ky5/

上偶然发现了这个https://github.com/knockout/knockout/wiki/Dirty-Tracking

这个概念是创建一个changetracker函数并将其指定为你的vm上的prop。

function changeTracker(objectToTrack, hashFunction) {    
hashFunction = hashFunction || ko.toJSON;
var lastCleanState = ko.observable(hashFunction(objectToTrack));

var result = {
    somethingHasChanged : ko.dependentObservable(function() {
        return hashFunction(objectToTrack) != lastCleanState()
    }),
    markCurrentStateAsClean : function() {
        lastCleanState(hashFunction(objectToTrack));   
    }
};

return function() { return result }
}
var viewModel = {someTextProperty: ko.observable("Hello"), boolProperty: ko.observable(false),
arrayItems: ko.observableArray([]),

addItem : function() { this.arrayItems.push("Another") }
};
viewModel.tracker = new changeTracker(viewModel);
ko.applyBindings(viewModel);

你仍然需要设置跟踪器,但是在使用ko映射时也应该能够实现这一点。

这看起来有点难看,但这个概念可以建立一个比没有更好的解决方案。 希望这有帮助!