65.9K
CodeProject 正在变化。 阅读更多。
Home

Knockout.js 入门以及在 ASP.NET Web Forms 中使用 Knockout.JS 进行 CRUD 操作

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (59投票s)

2013 年 12 月 11 日

CPOL

10分钟阅读

viewsIcon

152518

downloadIcon

8970

本文将介绍 Knockout.js 以及如何在 ASP.NET Web Forms 中使用 Knockout.JS 进行 CRUD 操作。

I) 引言

在过去的几年里,开发范式一直在快速变化。已经引入了开箱即用的技术,可以开发具有快速、可扩展、易于维护和易于使用的结构化应用程序。Knockout.JS 也是这类新兴技术的一个例子。我借此机会以我的方式解释这个概念和主题。

我们将遵循一个路线图,从基础到高级水平讨论这项技术。

II) 我们的路线图

我们将分两部分学习 Knockout.JS:

  1. 第一部分:使用 Knockout.js 和 Entity Framework 入门 Knockout.js 以及在 ASP.NET Web Forms 中进行 CRUD 操作。
  2. 第二部分在 MVC4 应用程序中使用 Knockout.JS 和 Entity Framework 完成端到端 CRUD 操作。

III) 第一部分:使用 Knockout.js 入门 Knockout.js 以及在 ASP.NET Web Forms 中进行 CRUD 操作

我们将首先介绍 knockout、MVVM 和观察者模式。然后,通过设置 knockout.js 中的基本环境,从而创建一个 ASP.NET Web Forms 应用程序并执行 CRUD 操作。

IV) Knockout

在当今不断变化的发展趋势中,数据驱动的应用程序很大程度上依赖于 JavaScript 和基于 JS 的库,如 jQuery。随着用户界面的日益丰富,客户端编程变得越来越复杂。在这种情况下,应用程序对数据绑定和依赖跟踪有很高的要求,以进一步扩展应用程序。Knockout JS 满足了客户端编程的这些丰富需求,并使开发者的生活轻松愉快。让我们详细讨论 KO。

Knockout.JS (KO) 主要是一个 JS 库,它使用客户端(浏览器)上的“Observable”ViewModel,遵循观察者模式方法,实现声明式绑定,从而使 UI 在绑定的数据发生更改时自动绑定和刷新。Knockout.JS 提供了自己的模板模式,帮助我们轻松地绑定我们的视图模型数据。KO 基于 MVVM 模式,即 Model-View-ViewModel。

正如架构所示,视图以双向绑定的方式与视图模型交互,即当模型更改时,视图会自行更新;当视图更新时,模型也会立即自行更新。

KO 提供了 3 个最重要的功能,如:

  • UI 自动刷新
  • 双向绑定
  • 模板化

KO 的整个想法源于这三个主要功能。KO 还帮助开发单页应用程序(SPA)。SPA 是当今开发富互联网应用程序(RIA)的一种开箱即用的新方法。

V) Model-View-View Model (MVVM)

当我们开发一个丰富的 UI 互联网应用程序时,我们使用服务器控件、HTML 控件创建视图(UI,如 HTML 和 aspx 页面),然后通过在这些视图后面编写业务逻辑来扩展我们的应用程序,例如事件处理、属性绑定、创建实体。当应用程序非常庞大时,这种方法会增加复杂性。在这里,我们需要分离关注点并维护应用程序,尤其是在客户端。

MVVM 模式包含三个关键部分:

  1. Model(业务规则、数据访问、模型类、UI 中显示的数据)
  2. View(用户界面(html, aspx, cshtml…))
  3. ViewModel(事件处理、绑定、业务逻辑)

Model 指的是我们的应用程序数据和领域模型,即实体。在传统的 ASP.NET Web 应用程序中,数据主要存储在数据库或文件中,UI 通过 Ajax 等客户端-服务器请求获取数据或直接绑定。

ViewModel 包含用户界面级别的操作/方法/函数,在模型数据上执行,以便将结果绑定到视图。这些操作包括在将数据绑定到 UI 之前需要执行的业务逻辑验证和检查。视图模型充当模型和视图之间的接口,并在绑定到视图之前充当模型的包装器。

View 是我们应用程序的用户界面。View 与 ViewModel 对话以调用某些方法/操作,如上所述。每当 ViewModel 中的数据更改时,View 都会自动更新。

MVVM 在用户界面(UI)和业务逻辑之间提供了清晰的关注点分离。

在 MVC 模式中,视图充当 Model(在视图中显示的数据)和 Controller(接收来自视图的数据并对其执行某些操作并提供响应的服务器端终结点)之间的代理。

VI) 用于双向绑定的 Observables

KO 在库中提供 Observables,用于绑定到 UI 元素,同时编写代码到视图模型,以便当视图更新数据时,模型会自行更新,反之亦然。例如,在以下代码中:

<tr>
    <td>Batch :</td>
    <td>
        <input data-bind="value: Batch" /></td>
    <td><span data-bind="text: Batch" /></td>
</tr>
<tr>
    <td>Address :</td>
    <td>
        <input data-bind="value: Address" /></td>
    <td><span data-bind="text: Address" /></td>
</tr>
<tr>
    <td>Class :</td>
    <td>
        <input data-bind="value: Class" /></td>
    <td><span data-bind="text: Class" /></td>
</tr>

上面的代码显示了视图的一部分,您可以看到元素绑定到 textvalue 等属性,这些属性由 KO 提供,而这些属性的右侧是属性键名,它们在视图模型中使用 observable 进行绑定,如下所示:

    var self = this;
    self.Batch = ko.observable();
    self.Address = ko.observable();
    self.Class = ko.observable(); 

所以这将在视图模型中是代码,无论如何,我们将详细讨论所有这些。

注意:Data-bind 是一个 HTML5 属性。

VII) 在 Visual Studio 中为 KO 设置环境

我们将逐步在 Visual Studio 中设置 Knockout js 环境。

先决条件是 Visual Studio 版本必须大于或等于 12。我使用的是 Visual Studio 2013 Express。

步骤 1:打开 Visual Studio 并创建一个简单的 ASP.NET 应用程序,我将其命名为 KOSetup。

步骤 2:右键单击项目,然后在上下文菜单中选择“管理 Nuget 程序包”以安装 JQuery 和 KO。

步骤 3:在搜索文本框中键入 jQuery 以获取最新兼容的 jQuery 库。单击“安装”以安装该库。

步骤 4:同样,在搜索文本框中搜索“knockout”并将 knockoutjs 库安装到您的应用程序中。

步骤 5:我们的解决方案将显示一个名为 Scripts 的文件夹,其中包含 jQuery 和 knockout 库。

步骤 6:现在右键单击项目并添加一个 aspx 页面,我将其命名为 LearnKO.aspx

步骤 7:同样,创建一个 JavaScript 文件并将其添加到项目中,我将其命名为 LearnKO.js

步骤 8:打开 learnKO.js 文件并将 jQuery 文件和 knockout.js 库文件拖到 LearKO.js 文件中,我们在下图中看到这两个文件的引用已在 js 文件中创建。我们这样做是因为它将为我们的 LearnKO.js 文件提供 jQuery 和 knockout 的智能感知支持。

步骤 9:在我们的 LearnKO.js 文件中编写 jQuery 的 document.ready 函数。Document.ready 函数在 HTML 文档对象模型加载到浏览器时触发。

这就是设置 knockout 所需的全部内容,现在我们知道如何在我们的应用程序中设置初始环境来使用 knockout.js

现在我们继续创建应用程序,与数据库通信,并创建模板和视图模型。

VIII) 创建 Knockout 应用程序

步骤 10:为了与数据库通信,以与我们添加 JQuery 和 KO 相同的方式添加 Entity Framework 库,安装 Entity Framework 库会将 EF DLL 添加到项目中。我们将使用 Microsoft 的 Entity Framework 与数据库通信。或者,还有许多其他方法可以与数据库通信,例如 ADO.NET、LINQ to SQL 等。但首先,创建一个要在 SQL Server 中使用的数据库。我为此提供了脚本。

步骤 11:右键单击项目并添加 ADO.NET Entity Data Model,单击“添加”,然后按照以下步骤操作:

步骤 12:下面是 Entity Data Model 的第二步。您可以从已创建的数据库中选择模型内容。因此,选择“从数据库生成”选项。单击“下一步”。

步骤 13:选择要添加的表,即 Student 表,如下图所示。将模型命名为 LearningKOModel。单击“完成”。

步骤 14:我们在解决方案中得到一些文件,如 context 和 tt 文件。我们还得到 Student.CS 文件,它将作为我们的服务器端域模型。context 类包含 Entity Framework 的数据通信方法。

步骤 15:在我们的 aspx.cs 页面中使用 Entity Framework 编写三个方法。一个方法用于获取所有 Students,另一个方法用于将学生保存/删除到/从数据库,如下所示。将它们标记为 WebMethod,以便可以从客户端调用它们。

代码如下

#region Public Web Methods.
        /// <summary>
        /// Gets Student Details
        /// </summary>
        /// <returns></returns>
        [WebMethod]
        public static Student[] FetchStudents()
        {
            LearningKOEntities dbEntities = new LearningKOEntities();
            var data = (from item in dbEntities.Students
                        orderby item.StudentId
                        select item).Take(5);
            return data.ToArray();
        }

        /// <summary>
        /// Saves Student Details
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [WebMethod]
        public static string SaveStudent(Student[] data)
        {
            try
            {
                var dbContext = new LearningKOEntities();
                var studentList = from dbStududent in dbContext.Students select dbStududent;
                foreach (Student userDetails in data)
                {
                    var student = new Student();
                    if (userDetails != null)
                    {
                        student.StudentId = userDetails.StudentId;
                        student.FirstName = userDetails.FirstName;
                        student.LastName = userDetails.LastName;
                        student.Address = userDetails.Address;
                        student.Age = userDetails.Age;
                        student.Gender = userDetails.Gender;
                        student.Batch = userDetails.Batch;
                        student.Class = userDetails.Class;
                        student.School = userDetails.School;
                        student.Domicile = userDetails.Domicile;
                    }
                    Student stud=(from st in studentList where 
                    st.StudentId==student.StudentId select st).FirstOrDefault();
                    if (stud == null)
                        dbContext.Students.Add(student);
                    dbContext.SaveChanges();
                }
                return "Data saved to database!";
            }
            catch (Exception ex)
            {
                return "Error: " + ex.Message;
            }
        }

        /// <summary>
        /// Deletes Student Details
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [WebMethod]
        public static string DeleteStudent(Student data)
        {
            try
            {
                var dbContext = new LearningKOEntities();
                var student = dbContext.Students.FirstOrDefault
                (userId => userId.StudentId == data.StudentId);
                if (student != null)
                {
                    if (student != null)
                    {
                        dbContext.Students.Remove(student);
                        dbContext.SaveChanges();
                    }
                }
                return "Data deleted from database!";

            }
            catch (Exception ex)
            {
                return "Error: " + ex.Message;
            }
        }
        #endregion

步骤 16:打开我们创建的 aspx 页面并添加以下代码。代码在 HTML 中提供与模型属性绑定的模板,一个用于添加 Student,另一个用于显示 Student 列表。

<table style="width:100%;" >
            <tbody>
                <tr>
                    <th style="width:100px;">Property Name</th>
                    <th style="width:100px;">Enter Value</th>
                    <th style="width:100px;">Example of two Way Binding</th>
                </tr>
                </tbody>
            <tr>
                <td>Student ID (int):</td>
                <td>
                    <input data-bind="value: StudentId" />
                    </td> <!--,valueUpdate:'keypress'-->
                <td><span data-bind="text: StudentId" /></td>
            </tr>
            <tr>
                <td>First Name :</td>
                <td>
                    <input data-bind="value: FirstName" /></td>
                <td  ><span data-bind="text: FirstName" /></td>
            </tr>
            <tr>
                <td>Last Name :</td>
                <td>
                    <input data-bind="value: LastName" /></td>
                <td><span data-bind="text: LastName" /></td>
            </tr>
            
            <tr>
                <td>Student Age (int) :</td>
                <td>
                    <input data-bind="value: Age" /></td>
                <td><span data-bind="text: Age" /></td>
            </tr>
            <tr>
                <td>Gender :</td>
                <td>
                    <select data-bind="options: Genders, value: 
                    Gender, optionsCaption: 'Select Gender...'"></select></td>
                <td><span data-bind="text: Gender" /></td>
            </tr>
            <tr>
                <td>Batch :</td>
                <td>
                    <input data-bind="value: Batch" /></td>
                <td><span data-bind="text: Batch" /></td>
            </tr>
            <tr>
                <td>Address :</td>
                <td>
                    <input data-bind="value: Address" /></td>
                <td><span data-bind="text: Address" /></td>
            </tr>
            <tr>
                <td>Class :</td>
                <td>
                    <input data-bind="value: Class" /></td>
                <td><span data-bind="text: Class" /></td>
            </tr>
            <tr>
                <td>School :</td>
                <td>
                    <input data-bind="value: School" /></td>
                <td><span data-bind="text: School" /></td>
            </tr>
            <tr>
                <td>Domicile :</td>
                <td>
                    <select data-bind="options: Domiciles, value: 
                    Domicile, optionsCaption: 'Select Domicile...'"></select>
                </td>
                <td><span data-bind="text: Domicile" /></td>
            </tr>
            <tr>
                <td colspan="3">
                    <button type="button" data-bind="click: 
                    AddStudent">Add Student</button>
                    <button type="button" data-bind="click: 
                    SaveStudent">Save Student To Database</button>
                </td>
            </tr>

        </table>
            </div>

         <div style="width:70%;float:left;display:inline-block;">
             <h2>List of Students</h2>
        <table style="width:100%;" data-bind="visible: 
        Students().length > 0" border="0">
            <tr>
                <th>Student Id</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Age</th>
                <th>Gender</th>
                <th>Batch</th>
                <th>Address</th>
                <th>Class</th>
                <th>School</th>
                <th>Domicile</th>
            </tr>
            <tbody data-bind="foreach: Students">
                <tr>
                    <td><span data-bind="text: StudentId" /></td>
                    <td>
                        <input data-bind="value: FirstName" /></td>
                    <td>
                        <input data-bind="value: LastName" /></td>
                    <td>
                        <input data-bind="value: Age" /></td>
                   
                    <td>
                        <select data-bind="options: $root.Genders, 
                        value: Gender"></select></td>
                    <td>
                        <input data-bind="value: Batch" /></td>
                    <td>
                        <input data-bind="value: Address" /></td>
                    <td>
                        <input data-bind="value: Class" /></td>
                    <td>
                        <input data-bind="value: School" /></td>
                    <td>
                        <select data-bind="options: $root.Domiciles, 
                        value: Domicile"></select></td>

                    <td><a href="#" data-bind="click: $root.
                    DeleteStudent">Delete</a></td>
                </tr>
            </tbody>
        </table>

有两个 HTML 表格,一个用于将学生添加到数据库,另一个显示所有学生,并具有删除学生的删除锚链接。这些模板属性将在视图模型中绑定,我们将在其中编写方法与数据库通信并调用我们在 aspx.cs 页面中创建的 Web Method。Viewmodel 还包含要绑定到这些属性的 observable。

步骤 17:现在是时候创建 ViewModel 了。打开 learnKO.js 文件并添加代码以获取、保存和删除学生,以及绑定到 HTML 页面控件的属性的 observable。

/// <reference path="jquery-2.0.3.min.js" />
/// <reference path="knockout-3.0.0.js" />

function Student(data) {
    this.StudentId = ko.observable(data.StudentId);
    this.FirstName = ko.observable(data.FirstName);
    this.LastName = ko.observable(data.LastName);
    this.Age = ko.observable(data.Age);
    this.Gender = ko.observable(data.Gender);
    this.Batch = ko.observable(data.Batch);
    this.Address = ko.observable(data.Address);
    this.Class = ko.observable(data.Class);
    this.School = ko.observable(data.School);
    this.Domicile = ko.observable(data.Domicile);
}

function StudentViewModel() {
    var self = this;
    self.Domiciles = ko.observableArray(['Delhi', 'Outside Delhi']);
    self.Genders = ko.observableArray(['Male', 'Female']);
    self.Students = ko.observableArray([]);
    self.StudentId = ko.observable();
    self.FirstName = ko.observable();
    self.LastName = ko.observable();
    self.Age = ko.observable();
    self.Batch = ko.observable();
    self.Address = ko.observable();
    self.Class = ko.observable();
    self.School = ko.observable();
    self.Domicile = ko.observable();
    self.Gender = ko.observable();

   
    self.AddStudent = function () {
        self.Students.push(new Student({
            StudentId: self.StudentId(),
            FirstName: self.FirstName(),
            LastName: self.LastName(),
            Domicile: self.Domicile(),
            Age: self.Age(),
            Batch: self.Batch(),
            Address: self.Address(),
            Class: self.Class(),
            School: self.School(),
            Gender: self.Gender()
        }));
         self.StudentId(""),
         self.FirstName(""),
         self.LastName(""),
         self.Domicile(""),
         self.Age(""),
         self.Batch(""),
         self.Address(""),
         self.Class(""),
         self.School(""),
        self.Gender("")
    };

    self.DeleteStudent = function (student) {

        $.ajax({
            type: "POST",
            url: 'LearnKO.aspx/DeleteStudent',
            data: ko.toJSON({ data: student }),
            contentType: "application/json; charset=utf-8",
            success: function (result) {
                alert(result.d);
                self.Students.remove(student)
            },
            error: function (err) {
                alert(err.status + " - " + err.statusText);
            }
        });
    };

    self.SaveStudent = function () {
        $.ajax({
            type: "POST",
            url: 'LearnKO.aspx/SaveStudent',
            data: ko.toJSON({ data: self.Students }),
            contentType: "application/json; charset=utf-8",
            success: function (result) {
                alert(result.d);
            },
            error: function (err) {
            alert(err.status + " - " + err.statusText);
        }
        });
    };

    $.ajax({
        type: "POST",
        url: 'LearnKO.aspx/FetchStudents',
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (results) {
            var students = $.map(results.d, function (item) {
                return new Student(item)
            });
            self.Students(students);
        },
        error: function (err) {
            alert(err.status + " - " + err.statusText);
        }
    })
}

$(document).ready(function () {
    ko.applyBindings(new StudentViewModel());
});

我们将 StudentViewModel() 创建为我们的主要视图模型 JavaScript 函数,它包含所有业务逻辑和操作。

我们在 document ready 函数中使用 KO 的 applyBindings 方法来绑定此视图模型。这将初始化我们的视图模型,ko.applyBindings(new StudentViewModel());

函数 function Student(data) 包含绑定到模型属性的 observable。

我们可以创建 Domiciles 和 genders 的 observable 数组来绑定到我们 HTML 的下拉列表。Ko 提供了这些 observable 以及其他此类属性来绑定到模型。

  • observable:用于定义模型/实体属性。如果这些属性与用户界面绑定,并且当这些属性的值更新时,与这些属性绑定的 UI 元素将立即用新值更新。

    例如:this.StudentId = ko.observable(“1”); - => StudentIdobservable 属性。KO 代表 Knockout.js 库的一个对象。

    observable 的值读取方式为 var id= this. StudentId ();
  • observableArrayobservableArray 表示需要通知的数据元素的集合。它用于绑定到 List 类元素。
    例如:this.Students = ko.observableArray([]);
  • applyBindings:这用于激活当前 HTML 文档或 HTML 文档中特定 UI 元素的 knockout。此方法的参数是 JavaScript 中定义的视图模型。此 ViewModel 包含 observableobservableArray 和各种方法。

本文还使用了各种其他类型的绑定:

  • click:表示添加到 UI 元素的单击事件处理程序,以便调用 JavaScript 函数。
  • value:这表示 UI 元素的 value 属性与 ViewModel 中定义的属性的双向绑定。

值绑定应与 <input><select><textarea> 一起使用。

  • visible:这用于根据传递给其绑定的值隐藏或显示 UI 元素。
  • Text:这表示传递给 UI 元素的参数的文本值。

步骤 18:将 js 文件和样式表(您可以创建自己的样式表文件)包含到 aspx 页面的 head 部分。

步骤 19:按 F5 运行应用程序,我们将看到一个具有以下 HTML 控件的页面:

学生列表显示数据库中的学生列表,绑定到 viewmodel 的事件。

尝试创建一个新学生并添加学生,然后将其保存到数据库,它将自动添加到右侧的列表中。

我们可以看到 Domicile 和 Genders 下拉列表已绑定到我们的 Viewmodel 的属性。

注意:不要在 StudentIdAge 中输入 string,因为这些字段没有进行验证,代码可能会中断。

创建学生

学生已添加到列表和数据库

任务完成!

现在您可以说您已经成为一名 knockout.js 开发者了。

IX) 结论

在本文中,我们学习了很多关于如何在 Visual Studio 中设置 knockout.js 的知识,包括大量的理论,并且还创建了一个示例应用程序来实践这个概念。有无数相关的文章和博客,您可以多多探索学习。在下一篇文章中,我将介绍使用 knockout js 和 Entity Framework 在 MVC4 中创建示例应用程序和执行 CRUD 操作。现在,为学到新概念而付出的努力而拍拍自己的背吧!

注意:本文中的部分图片来自 Google 搜索。

您可以在 csharppulse.blogspot.in 上关注我的文章。

祝您编码愉快。

© . All rights reserved.