Knockout.js 如何在ViewModel敲除中调用函数

Knockout.js 如何在ViewModel敲除中调用函数,knockout.js,Knockout.js,我有一个模型叫做客户: function customer(id, name, age, comments) { var self = this; self.Id = id; self.Name = name; self.Age = age, self.Comments = comments; self.addCustomer = function () { $.ajax({ url: "/api

我有一个模型叫做客户:

function customer(id, name, age, comments) {
    var self = this;

    self.Id = id;
    self.Name = name;
    self.Age = age,
        self.Comments = comments;

    self.addCustomer = function () {
        $.ajax({
            url: "/api/customer/",
            type: 'post',
            data: ko.toJSON(this),
            contentType: 'application/json',
            success: function (result) {
                //SOMETHINGS WRONG HERE
                customerVM();
            }
        });
    }
}
添加客户后,客户列表不会自动更新。在模型中调用customerVM()会进入viewModel函数,但不会进入getCustomers函数,因此我一定是调用viewModel时出错了。这就是我从调试中看到的

显示列表的函数位于viewModel中:

function customerVM() {
    var self = this;
    self.customers = ko.observableArray([]);
    self.getCustomers = function () {
        self.customers.removeAll();
        $.getJSON("/api/customer/", function (data) {
            $.each(data, function (key, val) {
                self.customers.push(new customer(val.Id, val.Name, val.Age, val.Comments));
            });
        });
    };
}
在添加客户后,我需要打电话给getCustomers。我该怎么做

这是客户的html

<table >
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Age</th>
            <th>Comments</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: customers" >
        <tr>
            <td data-bind="text: Id"></td>
            <td data-bind="text: Name"></td>
            <td data-bind="text: Age"></td>
            <td data-bind="text: Comments"></td>
        </tr>
    </tbody>
</table>
<br />
<input type="button" id="btnGetCustomers" value="Get Customers" data-bind="click: getCustomers" />

身份证件
名称
年龄
评论


我认为您的设计实际上有一些缺陷。首先,在调用
ko.applyBindings(vm)之后,您不希望在任何时候调用
customerVM()
(我在html中的任何地方都看不到)

在html页面的某个地方,您应该有:

<script type="text/javascript">
    var vm = new customerVM();
    ko.applyBindings(vm);
</script>

如果您按照Tom的建议执行了应用程序绑定:

<script type="text/javascript">
    var vm = new customerVM();
    vm.getCustomers();
    ko.applyBindings(vm);
</script>

尽管如此,我同意Tom的观点,将addCustomer方法移到根模型中更合适。

我认为您在这里提出的更深层次的问题是如何在浏览器中管理数据并使其与服务器上的数据保持同步。我昨天回答了一个类似的问题,你可以在这里看到:

在您的问题和代码中,看起来您正在尝试向服务器插入新客户,然后在插入后将整个客户列表读回视图模型。您可能有一个您没有提到的需求,但通常这种模式是不必要的

插入到服务器后,需要从服务器读取的最常见情况是为刚才添加的对象检索服务器生成的标识符。对于大多数MV*浏览器端框架(包括Knockout),一种常见的模式是“插入”api调用返回新元素的ID(或需要返回多少数据)只需使用新ID更新该模型的客户端版本。如果ID属性是可观察的,Knockout将自动更新您的UI。下面是一个例子:

var customer = function(name, age, comments){
    var self = this;
    self.id = ko.observable();//unknown when created in the browser
    self.name = ko.observable(name);
    self.age = ko.observable(age);
    self.comments = ko.observable(comments);
}

var customersViewModel = function(){
    var self = this;
    self.customers = ko.observableArray([]);
    self.addCustomer = function(customer){
        self.customers.push(customer);
        $.ajax({
            url: "/api/customer/add",
            type: 'post',
            data: ko.toJSON(this),
            contentType: 'application/json',
            success: function (result) {
                //assuming result will contain the server-side customer id
                //we provide that value to our customer's id observable
                //and knockout will update the UI
                customer.id(result.newCustomerId);
                //no need to update the entire array, and 
                //our 'customer' has already been pushed into our 
                //observable array so we're done. 
            }
        });
    }
}
当您的客户处于“挂起”状态时(当浏览器等待服务器响应insert api调用时),您知道该客户不会有ID。您可以在绑定中使用该ID向您的客户应用“挂起”类,如下所示:

self.addCustomer = function () {
    $.ajax({
        url: "/api/customer/",
        type: 'post',
        data: ko.toJSON(this),
        contentType: 'application/json',
        success: function (result) {
           vm.getCustomers(); //*******THIS IS THE CHANGE YOU NEED
        }
    });
}
<tbody data-bind="foreach: customers" >
    <tr data-bind="css : {'pending': !id()}">
        <td data-bind="text: id"></td>
        <td data-bind="text: name"></td>
        <td data-bind="text: age"></td>
        <td data-bind="text: comments"></td>
    </tr>
</tbody>

我希望这有帮助

在模型中调用customerVM()会进入viewModel函数,但不会进入getCustomers函数,因此我一定是调用viewModel时出错了。这就是我从调试中看到的
<tbody data-bind="foreach: customers" >
    <tr data-bind="css : {'pending': !id()}">
        <td data-bind="text: id"></td>
        <td data-bind="text: name"></td>
        <td data-bind="text: age"></td>
        <td data-bind="text: comments"></td>
    </tr>
</tbody>