KnockoutJs:Observable数组不使用最新模型数据更新视图

时间:2013-06-06 19:49:10

标签: jquery knockout.js

基本上问题是,当我点击链接时,它最初显示例如2条记录。但是,当我关闭页面并再次点击链接时,它会向我显示模型的更新记录,因为我正在调用控制器方法,该实习生返回Json resultData。但它不是那样工作只是将视图列表附加到自身并显示包含4条记录的视图。如果我反复打开窗口,它会显示像2,4,8,16 ......这样的记录:(

我的代码如下所示:

File1.cshtml:

<div id="Section1">
    <div>
        <span>
            <a href="javascript:void(0);" data-bind="click: OnClick">Click here</a>
        </span>
    </div>
</div>

File1.js:

var Section1VM = {
    OnClick: function () {
        $.ajax({
            type: 'POST',
            url: '/controller/View/',
            success: function (resultData) {
                initSection2VM(resultData);  function declared in File2.js
            },
            dataType: 'json'
        });
    }
};
Ko.applybinding (Section1VM , document.getElementById("Section1"))

File2.js

function initSection2VM(resultData) {
    var counter = 0
    var Section2VM = {
        List: ko.observableArray([]),
        ListCount:ko.observable()
    };
    Section2VM.List([]);
    ko.utils.arrayForEach(resultData, function (entry) {
        Section2VM.List.push(entry);
        counter++;
    });
    Section2VM.ListCount(counter);
    ko.applyBindings(Section2VM , document.getElementById("Section2"));
};

File2.cshtml

<div class="whiteContent" id="Section2">
    <tbody data-bind="foreach: List()">
        <tr>
            <td><span data-bind="text: SomeDate"></span></td>
            <td><span><a href="#" data-bind="attr: { href: SomeLink }, text: SomeNumber">   
            </a></span></td>
        </tr>
    </tbody>
</div>

代码说明:

  1. 点击“点击此处”链接将调用File1.js中的“OnClick”
  2. “OnClick”将给出ajax调用以从控制器获取更新列表。控制器返回Json结果起作用。
  3. “OnClick”成功后将调用initSection2VM(resultData);它在File2.js中声明并传递Json resultdata。
  4. 将resultData推送到Section2VM.List,然后推送到ko.applyBindings(Section2VM,document.getElementById(“Section2”));
  5. MeesageCenterPopUpSection正在加载file2.cshtml

2 个答案:

答案 0 :(得分:1)

问题是你多次调用ko.applyBindings。看看,这个方法在被调用时,链接一些Observable对象和应该代表它的DOM节点。每次更新此Observable对象时,其DOM表示也会更新自身 - 毕竟这是observable的含义。调用ko.applyBindings 更新代表是错误的 - 而在some cases Knockout设法自行修复情况,在others中它只是无助。

从理论到实践,解决问题的最简单方法是:

var initSection2VM = (function() {
    var counter = 0;
    var Section2VM = {
        List: ko.observableArray([]),
        ListCount:ko.observable()
    };
    ko.applyBindings(Section2VM, document.getElementById("Section2"));    
    return function(resultData) {
        Section2VM.List([]);
        ko.utils.arrayForEach(resultData, function (entry) {
            Section2VM.List.push(entry);
            counter++;
        });
        Section2VM.ListCount(counter);
    }
})();

此处我已定位Section2VM定义并立即调用applyBindings。结果函数将能够使用它,但对于外部世界,它将是不可见的。

这里有一个simplified demo来表明这一点。


替代方法是在第一次调用后重写函数本身:

function initSection2VM(resultData) {
    var counter = 0;
    var Section2VM = {
        List: ko.observableArray([]),
        ListCount:ko.observable()
    };
    ko.applyBindings(Section2VM, document.getElementById("Section2"));
    initSection2VM = function(resultData) {
        Section2VM.List([]);
        ko.utils.arrayForEach(resultData, function (entry) {
            Section2VM.List.push(entry);
            counter++;
        });
        Section2VM.ListCount(counter);
    };
    initSection2VM(resultData);
};

Demo

答案 1 :(得分:1)

解决上述问题。实际上问题是我在函数中不必要的绑定KO代码。我已经做了以下代码更改。

    $(function () { // docuement.ready function. 
        ko.applyBindings(Section2VM, document.getElementById("Section2"));
    });
    //Define globally 
    var Section2VM= {
        List: ko.observableArray([]),
        ListCount: ko.observable()
    };

    function initSection2VM (resultData) {
        var counter = 0
        Section2VM.List([]);
        ko.utils.arrayForEach(resultData, function (entry) {
            Section2VM.List.push(entry);
            counter++;
        });
        Section2VM.ListCount(counter);
    };