淘汰视图模型:为什么自我是全球性的?

时间:2013-06-09 19:45:36

标签: mvvm knockout.js durandal

我开始为具有不同过滤器小部件的搜索引擎编写一个durandal应用程序。我开始根据我在几个教程中看到的以下标准对视图模型进行编码(参见下面的示例,没有进一步说明),但是当我在“self”上分配一个具有相同名称的函数时,我遇到了问题。两种不同的视图模型。

我注意到当我开始复制现有的小部件时:在开始时结果集是混合的,函数不会被调用而没有任何错误......然后连续改变了可观察和函数名称,最后我只是通过改变它才能使它工作功能名称。 (例如self.facets - > self.facetsPA等) 我花了一段时间才找到它,很高兴知道按时完成项目,但这似乎不是一个好习惯,我觉得我可能做错了(通过分配自我对象的所有功能? )。

感谢您的一些解释。干杯,丹尼斯

define(['durandal/http', 'durandal/app', 'durandal/system','durandal/plugins/router'],     function (http, app, system, router) {
var self = this;

var PatentOfficeItem = function(id,name) {
    this.id = ko.observable(id);
    this.name = ko.observable(name);
};

self.facetsPA = ko.observableArray([]);
self.selectablePAFacets =  ko.computed(function() {
    var results = [];
    ko.utils.arrayForEach(self.facetsPA(), function(item) {
        var o = item.key();
        if (!self.officeExists(o))
            results.push(item);

    });
    return results;
});

self.selectedPatentOffices = ko.observableArray([]);
self.officeToAdd = ko.observable("");
self.addPatentOffice = function(item) {
    self.selectedPatentOffices.push(item);
};

self.removePatentOffice = function(item) {
    self.selectedPatentOffices.remove(item);
    var active = router.activeRoute();
    if (active.hash == "#/results/show") {
        app.trigger('PatentSearch:newQuery', 1);
    }
};

self.officeExists = function(code) {
    var result = false;
    ko.utils.arrayForEach(self.selectedPatentOffices(), function(item) {
        if (item.toString()==code.toString())
            result = true;
    });
    return result;
};

self.onCheckFacet = function(f) {
    var key = f.key();
    var value = f.value();
    var checked = f.checked();
    if (!self.officeExists(key))
        self.addPatentOffice(key);
    app.trigger('PatentSearch:newQuery', 1);
};

self.onCheckOffice = function(f) {
    //alert(JSON.stringify(f));
    self.removePatentOffice(f);
    app.trigger('PatentSearch:newQuery', 1);
};

self.getSetDifference2 = function(list1,list2) {
    var difference = [];
    var lookup = {};
    for (var j in list2) {
        var id = list2[j].id;
        lookup[list2[j].id] = list2[j].name;
    }
    for (var i in list1) {
        var id2 = list1[i].id;
        //alert(id);
        //if (lookup[id] == undefined ||lookup[id] === undefined) {
        if (!(id2 in lookup)) {
            difference.push(JSON.stringify(list1[i]));
            //break;
        }
    }
    //alert(JSON.stringify(difference));
    return difference;
};

return {
    activate: function () {},
    viewAttached: function() {
        setTimeout(function() {

            $(".patentFacetMulti").typeahead({
                source: function (query, process) {
                    return $.ajax({
                        url: "/assets/Content/patentoffices.json",
                        type: 'get',
                        data: {},
                        dataType: 'json',
                        success: function (result) {
                            var resultList = result.map(function (item) {
                                var aItem = { id: item.id, name: item.name };
                                return aItem;//JSON.stringify(aItem);
                            });
                            //return process(resultList);
                            return process(self.getSetDifference2(resultList,self.selectedPatentOffices()));
                        }
                    });
                },

                matcher: function (obj) {
                    var item = JSON.parse(obj);
                    return (~item.name.toLowerCase().indexOf(this.query.toLowerCase()) || ~item.id.toLowerCase().indexOf(this.query.toLowerCase()));
                },

                sorter: function (items) {
                    var beginswith = [], caseSensitive = [], caseInsensitive = [], item;
                    while (aItem = items.shift()) {
                        var item = JSON.parse(aItem);
                        if (!item.name.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(JSON.stringify(item));
                        else if (~item.name.indexOf(this.query)) caseSensitive.push(JSON.stringify(item));
                        else caseInsensitive.push(JSON.stringify(item));
                    }

                    return beginswith.concat(caseSensitive, caseInsensitive)

                },


                highlighter: function (obj) {
                    var item = JSON.parse(obj);
                    var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
                    var n = item.name.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
                        return '<strong>' + match + '</strong>'
                    });
                    var m = item.id.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
                        return '<strong>' + match + '</strong>'
                    });
                    return ""+m+"- " + n;
                },

                updater: function (obj) {
                    var item = JSON.parse(obj);
                    //$('#IdControl').attr('value', item.id);
                    self.addOffice(item);

                    var active = router.activeRoute();
                    if (active.hash == "#/results/show") {
                        app.trigger('PatentSearch:newQuery', 1);
                    }


                    //$(this).val("");
                    return "";
                }
            });

        },500);
    },
    selectedPatentOffices:selectedPatentOffices,
    facetsPA:facetsPA
};

});

2 个答案:

答案 0 :(得分:0)

如果您正在谈论Durandal对小部件的定义中的widgets而不是那些需要返回构造函数以确保它们可以多次实例化的小部件。上面的例子改为返回单例。

http://durandaljs.com/documentation/Creating-A-Widget/

define(function(require) {
    var widget = require('durandal/widget');

    var ctor = function(element, settings) {
        this.settings = settings;
    };

    ctor.prototype.getHeaderText = function(item) {
        if (this.settings.headerProperty) {
            return item[this.settings.headerProperty];
        }

        return item.toString();
    };

    ctor.prototype.afterRenderItem = function(elements, item) {
        var parts = widget.getParts(elements);
        var $itemContainer = $(parts.itemContainer);

        $itemContainer.hide();

        $(parts.headerContainer).bind('click', function() {
            $itemContainer.toggle('fast');
        });
    };

    return ctor;
});

答案 1 :(得分:0)

感谢您的回答。我的小部件必须是单例,因为我必须从其他视图模型访问和填充它们。我的问题也不是关于小部件(我更改了标题),我只是想知道为什么自我命名空间是全局的,当我使用上面的做法时,我不能在不同的视图模型上使用相同的方法名称两次。而我在这里可能做错了什么。由于这不是完全特定的问题,但一般来说更多的淘汰/ mvvm,所以也许标题之前是误导。

我主要是参考这篇文章(“管理这个”)

http://knockoutjs.com/documentation/computedObservables.html

我认为使用requirejs / knockout / durandal的整个意义是你可以拥有具有单独命名空间的视图模型,从而在javascript中产生更好的编程风格。作为自我全球化,对我来说没有意义,与不使用requirejs相比,我无法看到更长编码时间的优势。

我知道有更好的方法来构建具有durandal的小部件,但这暂时超出了我的范围。谢谢