将knockoutjs视图模型传递给多个ajax调用

3

我有一个函数,它会进行ajax调用以获取初始数据并将其保存到视图模型中。然后,我将返回的视图模型(对数据进行字符串化)传递到另一个函数中,该函数再进行另一次ajax调用,以此类推。每个函数都绑定在onclick按钮事件上。只有当我将它放在document.ready中时,才能将初始视图模型传递给其他函数。我从每个函数中获取的数据是100%正确的。但是,每当我绑定视图模型时,它就会覆盖先前的绑定,值不会保留。以下是代码:

JavaScript

<

script type="text/javascript" language='javascript'>
        var MyProject = {};
        var viewModel;
        MyProject.viewModel = "";
        var invoiceModel;
        $(document).ready(function InitializeInvoice() {
                    $.ajax({
                        type: "Post",
                        url: "Default.aspx/InitializeModel",
                        data: {},
                        contentType: "application/json; charset=utf-8",
                        dataType: "json",
                        async: false,
                        success: initializesinvoice
                    });
                function initializesinvoice(msg) {
                    var defaultdata = msg.d.Data;
                    invoiceModel = defaultdata;
                    MyProject.viewModel = ko.mapping.fromJS(invoiceModel);
                    ko.applyBindings(MyProject.viewModel)
                };
            })
            function GetVendorInvoiceDefaults() {
                MyProject.viewModel = JSON.stringify(invoiceModel);
                var data = '{invoice:' + MyProject.viewModel + '}';
                $.ajax({
                    type: "Post",
                    url: "Default.aspx/GetVendorInvoiceDefaults",
                    data: data,
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    async: false,
                    success: GetVendorInvoiceDefaultsSuccess
                });
            }
            function GetVendorInvoiceDefaultsSuccess(msg) {
                var defaultdata = msg.d.Data;
                invoiceModel = defaultdata;
                MyProject.viewModel = ko.mapping.fromJS(invoiceModel);
                ko.applyBindings(MyProject.viewModel)
            };

             function GetVendorCode() {
                var vendormodel = JSON.stringify(invoiceModel);
                var data = '{invoice:' + vendormodel + '}';
                $.ajax({
                    type: "Post",
                    url: "Default.aspx/GetVendorCode",
                    data: '{invoice:' + vendormodel + '}',
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    async: false,
                    success: GetVendorCodeSucess
                });
            }

            function GetVendorCodeSucess(msg) {
                var defaultdata = msg.d.Data;
                MyProject.viewModel = ko.mapping.fromJS(defaultdata);
                ko.applyBindings(MyProject.viewModel)
            };
#HTML#
    <p> Invoice Description <asp:TextBox ID="txtdesc" runat="server" data-bind="value:InvoiceDescription"> </asp:TextBox></p>    
    <p> Distribution Code <asp:TextBox ID="txtdistcode" runat="server" data-bind="value:DistributionCode"></asp:TextBox></p>
    <p> Vendor Code <asp:TextBox ID="txtvendor" runat="server" data-bind="value:VendorCode" ></asp:TextBox></p>
    <p> <button onclick="InitializeInvoice()">InitializeInvoice</button></p>
    <p><button id="btndefaults" onclick="GetVendorInvoiceDefaults()">GetVendorInvoiceDefaults</button></p>
    <p><button id="btnvendor" onclick="GetVendorCode()">GetVendorCode</button><p>
</pre>

#ASPX file#
    namespace WebApplication9
    {

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            

        }

        protected override void OnLoad(EventArgs e)
        {
            if (IsPostBack)
            {
            
                clientSideIsPostBack.Value = "Y";
            }
            
            else
                    clientSideIsPostBack.Value = "N";

                base.OnLoad(e);
        }
    
        [WebMethod]
        public static JsonResult  InitializeModel()
        {

            var Invoice = new Invoice() { InvoiceNumber = "1235", InvoiceDescription = "Hello World", DistributionCode = "" };
            JsonResult r = new JsonResult();
            r.Data = Invoice;
            return r;    //serializer.Deserialize(Invoice, typeof(Invoice)) as JsonResult;
        }

        [WebMethod]
        public static JsonResult GetVendorInvoiceDefaults(Invoice invoice)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            invoice.DistributionCode = "HELLO WORLD";
            JsonResult r = new JsonResult();
            r.Data = invoice;
            return r;
            //return new JsonResult() { Data = invoice };
        }

        [WebMethod]
        public static JsonResult GetVendorCode(Invoice invoice)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            invoice.VendorCode = "AHM";
            JsonResult r = new JsonResult();
            r.Data = invoice;
            return r;
        }

    }


    public class Invoice
    {
        private string distributionCode;
        private string vendorcode;

        public string InvoiceNumber { get; set; }
        public string InvoiceDescription { get; set; }
        public string DistributionCode 
        {
            get
            {
                return distributionCode ?? string.Empty;
            }
            set
            {
                distributionCode = value;
            }
        }
        public string VendorCode 
        {
            get
            {
                return vendorcode ?? string.Empty;
            
            }
            set 
            {
                vendorcode = value;
            
            }
        }
        
    }
    }
1个回答

3

因此,您永远不应在一个地方或一个div上多次调用此方法:ko.applyBindings(MyProject.viewModel)

一旦为viewmodel应用了绑定,它们就会起效。 您永远不要重复此步骤! 这非常重要。当MyProject.viewModel中的值更新时,绑定会自动更新HTML。这就是整个过程的关键。当您多次调用applyBindings时,会产生各种意想不到的行为。

设置好viewModel,只需应用一次绑定,然后使所有其他代码正确更新viewmodel。我建议在document.ready处理程序中执行此操作,执行任何其他操作之前,如连接ajaxy内容等。

其次,在使用KO映射插件时,根据文档,您可以像这样更新整个viewmodel:ko.mapping.fromJS(data, viewModel); 每次调用MyProject.viewModel = ko.mapping.fromJS(invoiceModel);都会覆盖您的viewmodel。

这是Knockout的另一个关键方面。因为observables是函数,所以您通过将新值作为参数传递来更新它们,而不是像普通变量一样重写它们。

正确的:

viewModel.observable(newValue)

错误的:

viewModel.observable = newvalue


谢谢您的评论。解决我的问题的方法是在页面加载时创建一个全局类对象,这样类成员始终可以在方法中使用。但我同意您提出的观点,都很有道理。谢谢! - Life is good
3
感谢让我花了六次时间阅读文档,最终弄明白了。顺便提一下,当前版本需要提供一个映射参数:ko.mapping.fromJS(data, {}, viewModel)。 - Nick Pearce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接