使用 jquery ajax 和 knockout.js 映射插件

Using jquery ajax with knockout.js mapping plugin

我正在尝试将 jquery 的 $.ajax 函数与 knockout.js 映射插件一起使用,在此使用测试 api:http://rest.learncode.academy/

返回的数据格式不正确。我的 js 看起来像这样:

    function FromDb(){

             $.ajax({
              type: 'GET',
              url: 'http://rest.learncode.academy/api/johnbob/friends',
              //dataType: "json",
              success: function(data) {
                console.log("I have friends!", data[0]); //returns all of johnbob's friends
                myResult = data[0];
            return myResult
                }
            });



//return{ name: 'test' }

    }


    function MaptoKo(frnd){
        var map = ko.mapping.fromJS(frnd);
        return map;
    }

    var obj={
        friends:ko.observable(new MaptoKo(new FromDb())),
    }

    ko.applyBindings(obj.friends);

因为 api return 是一个数组,我只需要一个对象,我使用数据 [0] 来获取数组中的第一项。当我注释掉 ajax 调用并取消注释 //return{ name: 'test' } 时,我得到了我想要的结果,我只是不确定为什么它不能使用 ajax打电话。

我花了几分钟才记住如何以正确的方式执行此操作,即从 AJAX 成功回调函数内部更新绑定。

问题是对 FromDb() 和 AJAX success 函数的调用断开。从 success 函数返回值是异步发生的,这意味着代码无法知道将值 returned 挂钩回 MaptoKo(new FromDb()) 调用。当您仅 return { name: 'test' }; 调用 FromDb() 时,它会 同步发生 ,因此结果会进入 MaptoKo 函数。

$.getJSON("/some/url", function(data) { 
    // Now use this data to update your view models, 
    // and Knockout will update your UI automatically 
})

So, all Knockout needs to help you do is: ...

  • For loading, update your view model using data that you’ve received using one of the above techniques

来源:Knockout JSON Data Docs

对于您的特定代码,这意味着如下内容:

function FriendsViewModel() {
    var self = this;
    self.friends = ko.observable();

    // Load the initial data
    $.ajax({
        type: 'GET',
        url: 'http://rest.learncode.academy/api/johnbob/friends',
        //dataType: "json",
        success: function(data) {
            //returns all of johnbob's friends
            console.log("I have friends!", data[0]);
            myResult = data[0];
            // Don't return the result, bind it to the viewmodel
            self.friends(myResult);
          }
      });
}

ko.applyBindings(new FriendsViewModel());

这在 Loading and Saving tutorial. Note that this no longer really makes use of the mapping plugin. To tie that in, following the advice of the mapping plugin docs:

中有很好的介绍

To create a view model via the mapping plugin, replace the creation of viewModel in the code above with the ko.mapping.fromJS function:

var viewModel = ko.mapping.fromJS(data);

This automatically creates observable properties for each of the properties on data. Then, every time you receive new data from the server, you can update all the properties on viewModel in one step by calling the ko.mapping.fromJS function again:

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);
$.(function (){

    // Load the initial data
    $.ajax({
        type: 'GET',
        url: 'http://rest.learncode.academy/api/johnbob/friends',
        //dataType: "json",
        success: function(data) {
            //returns all of johnbob's friends
            console.log("I have friends!", data[0]);
            myResult = data[0];
            // Don't return the result, bind it to the viewmodel
            var viewModel = ko.mapping.fromJS(myResult);
            // Only bind once after the initial load.
            // If you save or reload data, don't reapply bindings
            ko.applyBindings(viewModel);
          }
      });
});

最后一个例子只是一个猜测,我自己从未使用过映射插件。但希望它能说明您不能只是 return 来自异步回调的结果。