KnockoutJS数据更新将内部函数写入UI

时间:2012-03-19 17:31:09

标签: javascript knockout.js

当我更新我的viewmodel时,我遇到了这个奇怪的问题...基本上每次更新时,似乎每个observable都会随机包含这些数据:

function observable() {    
        if (arguments.length > 0) {    
            // Write               

            // Ignore writes if the value hasn't changed    
            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {    
                observable.valueWillMutate();    
                _latestValue = arguments[0];    
                observable.valueHasMutated();    
            }

            return this; // Permits chained assignments    
        } else {    
            // Read    
            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation

            return _latestValue;
        }    
    }

我一直在使用KnockoutJS,我从来没有见过这样的东西。我的猜测是它与我的模板绑定有关,但我真的不确定。我要深入研究它,但我想我会在这里发布它,以防其他人遇到这个问题,或者有解决方案。就像我说的那样,它不会一直发生,只是偶尔发生。

////更多信息////

所以Matt在下面引用了这个问题(http://stackoverflow.com/questions/9763211/option-text-becomes-a-function-string-after-updated-with-fromjs),这大致是同一个问题。唯一的区别是我在这样的样式中使用本机模板绑定:

<div data-bind="template: {name: 'issueTemplate', data: incidents}"></div>

<script id="dashboardIssueTemplate" type="text/html">       
    <!--ko foreach: $data-->    
    <div data-bind="text: title"></div>
</script>

当我将observableArray传递给模板绑定器时,我假设KnockoutJS自行处理解包。我知道在这个例子中我不能说“title()”,因为那不存在。我应该用像$ root.title()这样的命令绑定吗?

////更多信息////

由于在一个页面上有两个“applyBindings”,似乎会出现此问题。我的应用程序包含一个外部窗口小部件,它在运行时将它的DOM添加到主机页面DOM。该小部件使用ko.applyBindings(vm,ROOTNODE)语法,该语法应该允许主机页面运行它自己的ko.applyBindings(hostVm)。

事实上,确实如此,每次刷新都能正常工作。但问题是主机页面在没有刷新的情况下执行viewModel更新。不知何故,UI呈现在每个数据绑定节点上吐出这个内部函数。我通过KnockoutJS调试并实际确认viewModel和rootNode是正确的......实际绑定之外的东西正在接管。

1 个答案:

答案 0 :(得分:1)

这与附加到模板中数据对象的“()”有关。我发现在第一次渲染(页面加载)期间编写模板如下:

<div data-bind="template: {name: 'issueTemplate', data: incidents}"></div>

<script id="dashboardIssueTemplate" type="text/html">       
    <div data-bind="text: title"></div>
</script>

工作得很好。但是,一旦在observableArray上运行更新,我的“title”对象就变成了该函数。如果我使用这种风格编写模板:

<div data-bind="text: title()"></div>

它似乎适用于每次更新。

我不确定为什么这是解决方案。从它的外观来看,传递给Knockout活页夹的数据对象在页面加载和更新上完全相同。我会将此作为答案发布,但在我理解为什么会发生这种情况之前,我不会将其标记为答案。