1

我正在使用 KnockoutJS 构建一个应用程序,该应用程序具有一个基本上充当顺序电子表格的组件。在不同的行上,用户可以定义变量或使用它们来表示一个值。

所以例如

x =2 
x  //2
x = 4
x  //4

我在继续添加新行的简单情况下工作。每行的输出函数检查并向后迭代以查看变量是否以前定义过。如果是,它使用它找到的第一个示例并将其设置为值。这在最初定义行时有效,并且在前一行更改后编辑一行时也有效。

但是,如果该变量的先前定义已更改、删除或添加,我希望更新变量。这种行为现在不存在。我尝试使用映射添加我自己的自定义依赖处理代码来跟踪变量,但它严重影响了性能。我想利用 Knockouts 依赖管理来解决这个问题,但我不确定最好的方法。这是我的代码结构的简要总结,如果需要,我很乐意添加更多细节。

calcFramework是我绑定到地图的视图模型对象。它由一个可观察的 Lines 列表、一个 varMap 和其他不相关的属性和函数组成

Line是一个自定义对象。相关代码如下

var Line = function (linenum,currline) {
    var self = this;
    self.varMap = {};
    self.input = ko.observable("");
    self.linenum = ko.observable(linenum); 

    self.lnOutput = ko.computed({
        read:function(){
           return outputFunction(self,self.input());
        },
        write:function(){},
        owner:self
    });
};

function  outputFunction(self,input) {
    try{
        var out = EQParser.parse(input,10,self);
        return  out.toString();
    }
    catch(ex){
        //error handling
    }
}

Line.prototype.getVar = function (varName, notCurrentLine) {
    if(typeof varName === "undefined"){
        return null;
    }
    //Actually don't want ones set in the current varMap, only past lines
    if(varName in this.varMap && notCurrentLine){
        return this.varMap[varName];
    }

    if (this.linenum() > 0) {
        var nextLine = calcFramework.lines()[this.linenum() - 1];
        return nextLine.getVar(varName,true);
    } else {
        //eventually go to global
        return calcFramework.varMap[varName];
    }
};

Line.prototype.setVar = function(varName,value){
    this.varMap[varName] = value;
};

SetVar 和 getVar 被传递给 eqParser,后者获取表达式的值,如果引用了变量,则根据需要调用这些函数。所以变量值没有显式传递给函数,因此敲除不会将其视为依赖项。但是我不确定如何将变量作为参数传递而不每次都遍历列表。

所以我的问题是,在这种设置下,跟踪变量赋值(和/或新赋值)的变化并更新引用该变量的行,同时保持良好性能的最佳方法是什么。

我知道我的问题很长,我试图删掉所有不必要的细节。感谢您的耐心阅读。

4

1 回答 1

1

我很想使用发布/订阅模型,使用类似Peter Higgins 的 PubSub jquery 插件

您的整个应用程序将订阅/侦听发布它们具有变量定义的事件的行。这会将任何变量名称与值一起存储在标准 javascript 哈希表中。当一个变量找到事件被一行发布时,应用程序会检查所有已知的变量,如果它发现它是对现有变量值的更改,它会发布一个变量更改事件。所有的行都会订阅那个事件。然后,他们可以检查是否有与该名称匹配的变量,并相应地更新值。

这是一些未经测试的代码,可以让您了解我的意思:

var app = function()
{
    var self = this;

    self.variables = {};
    $.subscribe('/variableAssigned', function (key, value)
        {
            // I think that this is the best way of checking that there is a variable
            // in the object
            if(self.variables.hasOwnProperty(key))
            {
                if(self.variables[key] !== value)
                {
                    $.publish('/variableChanged', [ key, value ]);
                }
            }
        });
}

在您的 Line 对象中:

$.subscribe('/variableChanged', function (key, value)
    {
        // loop through varMap and see if any of them need updating.
    });
于 2013-01-28T09:58:29.320 回答