[译]使用Knockout和ASP.NET的单页应用程序
By robot-v1.0
本文链接 https://www.kyfws.com/applications/single-page-app-using-knockout-and-asp-net-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 6 分钟阅读 - 2879 个词 阅读量 0[译]使用Knockout和ASP.NET的单页应用程序
原文地址:https://www.codeproject.com/Articles/410238/Single-Page-App-Using-Knockout-and-ASP-NET
原文作者:Bangla Gopal Surya Prakash
译文由本站 robot-v1.0 翻译
前言
How to create a sample single page application using Knockout and ASP.NET.
如何使用Knockout和ASP.NET创建示例单页应用程序.
介绍(Introduction)
在本文中,我将讨论如何使用Knockout和ASP.NET创建示例单页应用程序.该应用程序根据用户,管理员用户,超级管理员用户等类型显示用户列表,并在选择用户后显示用户详细信息.(In this article, I will discuss how to create a sample single page application using Knockout and ASP.NET. This app shows a list of users based on types like Users, Admin Users, Super Admin Users, and shows user details upon selection of a user.)
对于构建此应用程序,我们应该具有Knockout,SAMMY库,WCF RESTful服务和JavaScript的基本知识.(For building this app, we should have basic knowledge of Knockout, SAMMY library, WCF RESTful services, and JavaScript.)
在继续阅读本文之前,让我们看一下Knockout的标准定义:(Before we jump on to the article, let’s have a look at the standard definition of Knockout:)
Knockout是一个JavaScript库,可帮助您使用干净的基础数据模型创建丰富的响应式显示和编辑器用户界面.每当您具有动态更新的UI部分时(例如,根据用户的操作进行更改或外部数据源更改时),KO都可以帮助您更简单,更可维护地实现它.(Knockout is a JavaScript library that helps you to create rich, responsive displays and editor user interfaces with a clean underlying data model. Any time you have sections of UI that update dynamically (e.g., changing depending on user’s actions or when an external data source changes), KO can help you implement it more simply and maintainably.)
Sammy.js(Sammy.js) 是一个出色的轻量级路由JavaScript库.当与Knockout配对使用时,您可以执行以下操作(来自教程网站或KnockoutJS):(is an excellent lightweight routing JavaScript library. You can do things like this to route when used in pair with Knockout (from the tutorials web site or KnockoutJS):)
- 创建WCF RESTful服务(Create a WCF RESTful Service)
- 创建一个ASP.NET网站(Create an ASP.NET website)
- 定义一个ViewModel(Define a ViewModel)
- 定义视图(Define View)
- 定义样式(Define Styles)
- 输出画面(Output screen)
创建WCF RESTful服务(Create a WCF RESTful Service)
我们将定义两种方法:(We will define two methods:)
GetUsers
:根据用户类型返回用户列表(: returns a list of users based on usertype)GetUserData
:根据用户ID和用户类型返回用户列表(: returns a list of users based on userid and usertype) 这些服务将返回JSON对象.代码如下所示.要了解有关如何构建RESTful服务的更多信息,请参见以下文章(These services would return a JSON object. The code is shown below. To know more about how to build a RESTful service, find my article at) http://www.codeproject.com/Articles/275279/Developing-WCF-Restful-Services-with-GET-and-POST(http://www.codeproject.com/Articles/275279/Developing-WCF-Restful-Services-with-GET-and-POST) .(.)
我将服务定义为(I have defined my service as)ServiceOne.svc(ServiceOne.svc),因此我的界面将是这样的:(, so my interface would we something like this:)
[ServiceContract]
public interface IServiceOne
{
[OperationContract(Name = "GetUsers")]
[WebInvoke(Method = "GET", UriTemplate = "GetUsers/utypeid/{userTypeId}",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
myCustomObject GetUsers(string userTypeId);
[OperationContract(Name = "GetUserData")]
[WebInvoke(Method = "GET", UriTemplate = "GetUserData/utypeid/{userTypeId}/uid/{userId}",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
users GetUserData(string userTypeId, string userid);
}
此外,为此,我定义了用户类别,(Also, to work on this I define my class of users,) myCustomObject
.(.)
这是定义:(Here is the definition:)
public class myCustomObject
{
public string userTypeId { get; set; }
public List<users> users { get; set; }
}
public class users
{
public string userid { get; set; }
public string usertypeid { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public string address { get; set; }
}
以下是接口中定义的方法的实现.我避免调用数据库,因为这是一个示例,并且已经定义了静态值:(Below is the implementation for the methods defined in the interface. I have avoided calling the database as this is a sample, and I have defined static values:)
public class ServiceOne : IServiceOne
{
public myCustomObject GetUsers(string userTypeId)
{
myCustomObject myObj = new myCustomObject();
myObj.userTypeId = userTypeId;
List<users> usersList = new List<users>();
if (userTypeId == "Users")
{
usersList.Add(new users() { usertypeid = "Users", userid = "1",
firstname = "user fname 1", lastname = "user lname 1", address = "user address 1" });
usersList.Add(new users() { usertypeid = "Users", userid = "2",
firstname = "user fname 2", lastname = "user lname 2", address = "user address 2" });
}
else if (userTypeId == "AdminUsers")
{
usersList.Add(new users() { usertypeid = "AdminUsers", userid = "3",
firstname = "admin user fname 1", lastname = "admin user lname 1",
address = "admin user address 1" });
usersList.Add(new users() { usertypeid = "AdminUsers", userid = "4",
firstname = "admin user fname 2", lastname = "admin user lname 2",
address = "admin user address 2" });
}
else if (userTypeId == "SuperAdminUsers")
{
usersList.Add(new users() { usertypeid = "SuperAdminUsers", userid = "5",
firstname = "super admin user fname 1", lastname = "super admin user lname 1",
address = "super admin user address 1" });
usersList.Add(new users() { usertypeid = "SuperAdminUsers", userid = "6",
firstname = "super admin user fname 2", lastname = "super admin user lname 2",
address = "super admin user address 2" });
}
myObj.users = usersList;
return myObj;
}
public users GetUserData(string userTypeId, string userid)
{
List<users> usersList = new List<users>();
usersList.Add(new users() { usertypeid = "Users", userid = "1",
firstname = "user fname 1", lastname = "user lname 1", address = "user address 1" });
usersList.Add(new users() { usertypeid = "Users", userid = "2",
firstname = "user fname 2", lastname = "user lname 2", address = "user address 2" });
usersList.Add(new users() { usertypeid = "AdminUsers", userid = "3",
firstname = "admin user fname 1", lastname = "admin user lname 1",
address = "admin user address 1" });
usersList.Add(new users() { usertypeid = "AdminUsers", userid = "4",
firstname = "admin user fname 2", lastname = "admin user lname 2",
address = "admin user address 2" });
usersList.Add(new users() { usertypeid = "SuperAdminUsers", userid = "5",
firstname = "super admin user fname 1", lastname = "super admin user lname 1",
address = "super admin user address 1" });
usersList.Add(new users() { usertypeid = "SuperAdminUsers", userid = "6",
firstname = "super admin user fname 2", lastname = "super admin user lname 2",
address = "super admin user address 2" });
users obj = (from user in usersList.Where(val => val.userid ==
userid && val.usertypeid == userTypeId)
select user).First();
return obj;
}
}
在IIS中托管您的服务,并使用URL对其进行测试,在我的情况下,它如下所示:(Host your service in IIS and test it by using the URL, in my case it is as follows:)http://localhost/wcfrestservice/ServiceOne.svc/GetUsers/id/Users(http://localhost/wcfrestservice/ServiceOne.svc/GetUsers/id/Users).(.)
通过单击它,您应该能够看到JSON对象.确保不使用端口号运行应用程序.(By clicking it, you should be able to see the JSON object. Make sure that you don’t run your application using port number.)
创建一个ASP.NET网站(Create an ASP.NET website)
创建一个ASP.NET网站并添加一个名为(Create an ASP.NET website and add a new webpage named)userslist.aspx(userslist.aspx).(.)
到此时,您必须已经了解KnockOut遵循MVVM模式,即Model,View,ViewModel模式.(By this time you must havce understood that KnockOut follows the MVVM pattern, i.e., Model, View, ViewModel pattern.)
将以下脚本引用添加到您的页面:(Add the below script reference to your page:)
<!-- JQUERY Library -->
<script type="text/javascript" src="http://learn.knockoutjs.com/Scripts/CDNHosted/jquery-1.7.1.min.js"></script>
<!-- KNOCKOUT Library -->
<script type="text/javascript" src="http://learn.knockoutjs.com/Scripts/Lib/knockout-2.1.0.js"></script>
<!-- SAMMY Library -->
<script src="http://learn.knockoutjs.com/scripts/lib/sammy.js" type="text/javascript"></script>
定义一个ViewModel(Define a ViewModel)
让我们将以下脚本代码添加到页面中,查看内联代码注释:(Let’s add the below script code to the page, see inline code comments:)
<script type="text/javascript">
function UsersViewModel() {
// Data
var self = this;
// defines usertypes
self.userTypes = ['Users', 'AdminUsers', 'SuperAdminUsers'];
// holds usertypeid, when usertype is selected
self.chosenuserTypeId = ko.observable();
// holds list of users for a selected usertype
self.chosenUserTypesData = ko.observable();
// hold userdata for a selected user
self.chosenUserData = ko.observable();
// Behaviours
self.goToUserType = function (usertypeid) { location.hash = usertypeid };
self.goToUserData = function (userdata) { location.hash = userdata.usertypeid + '/' + userdata.userid };
// Client-side routes, can be defined by using SAMMY library
Sammy(function () {
// below segment is used to fetch userslist based on usertypeid
this.get('#:usertypeid', function () {
// sets selected usertypeid
self.chosenuserTypeId(this.params.usertypeid);
// destroy userdata, because at this point we need to have userslist instead of userdata
self.chosenUserData(null);
// make a call to wcf restful service, to fetchs users based on usertypeid
// response from service would contains "userslist", which is filled
// into chosenUserTypesData, whenever we statement "self.chosenUserTypesData"
$.get("http://localhost/wcfmailservice/ServiceOne.svc/GetUsers/Id/" +
this.params.usertypeid, self.chosenUserTypesData);
});
// below segment is used to fetch userdata based on usertypeid & userid
this.get('#:usertypeid/:userid', function () {
// sets selected usertypeid
self.chosenuserTypeId(this.params.usertypeid);
// destroys userslist, because at this point we need to have userdata instead of userslist
self.chosenUserTypesData(null);
// make a call to wcf service, to fetch user data based on usertypeid & userid
$.get("http://localhost/wcfmailservice/ServiceOne.svc/GetUserData/utypeid/" +
this.params.usertypeid + "/uid/" + this.params.userid, self.chosenUserData);
});
// when page load happens show default data, using sammy routing mechanism
this.get('', function () { this.app.runRoute('get', '#Users') });
}).run();
};
// allows to bind viewmodel defined above
ko.applyBindings(new UsersViewModel());
</script>
定义视图(Define a View)
<!-- Users Types, to show list of usertypes based on usertype defined -->
<!-- foreach allows to iterate through the usertypes declared -->
<ul class="userTypes" data-bind="foreach: userTypes">
<li data-bind="text: $data,
css: { selected: $data == $root.chosenuserTypeId() },
click: $root.goToUserType"></li>
</ul>
<!-- Users Grid: with keyword allows below section to be
shown only when data in chosenUserTypesData is available -->
<table class="userslist" data-bind="with: chosenUserTypesData">
<thead><tr><th>First Name</th><th>Last Name</th><th>Address</th></tr></thead>
<tbody data-bind="foreach: users">
<tr data-bind="click: $root.goToUserData">
<td data-bind="text: firstname"></td>
<td data-bind="text: lastname"></td>
<td data-bind="text: address"></td>
</tr>
</tbody>
</table>
<!-- Selected User: with key allows to below section to be shown only when chosenUserData is available-->
<div class="userData" data-bind="with: chosenUserData">
<div class="userdetails">
<p><label>First Name</label>: <span data-bind="text: firstname"></span></p>
<p><label>Last Name</label>: <span data-bind="text: lastname"></span></p>
</div>
</div>
定义样式(Define styles)
.userTypes { background-color: #bbb; list-style-type: none; padding: 0; margin: 0; border-radius: 7px;
background-image: -webkit-gradient(linear, left top, left bottom,
color-stop(0, #d6d6d6), color-stop(0.4, #c0c0c0), color-stop(1,#a4a4a4));
margin: 10px 0 16px 0;
font-size: 0px;
}
.userTypes li:hover { background-color: #ddd; }
.userTypes li:first-child { border-left: none; border-radius: 7px 0 0 7px; }
.userTypes li { font-size: 16px; font-weight: bold; display: inline-block; padding: 0.5em 1.5em;
cursor: pointer; color: #444; text-shadow: #f7f7f7 0 1px 1px;
border-left: 1px solid #ddd; border-right: 1px solid #888; }
.userTypes li { *display: inline !important; } /* IE7 only */
.userTypes .selected { background-color: #444 !important; color: white;
text-shadow:none; border-right-color: #aaa; border-left: none;
box-shadow:inset 1px 2px 6px #070707; }
.userslist { width: 100%; table-layout:fixed; border-spacing: 0; }
.userslist thead { background-color: #bbb; font-weight: bold; color: #444; text-shadow: #f7f7f7 0 1px 1px; }
.userslist tbody tr:hover { cursor: pointer; background-color: #68c !important; color: White; }
.userslist th, .userslist td { text-align:left; padding: 0.4em 0.3em;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.userslist th { border-left: 1px solid #ddd; border-right: 1px solid #888; padding: 0.4em 0 0.3em 0.7em; }
.userslist th:nth-child(1), .userslist td:nth-child(1) { width: 20%; }
.userslist th:nth-child(2), .userslist td:nth-child(2) { width: 15%; }
.userslist th:nth-child(3), .userslist td:nth-child(3) { width: 45%; }
.userslist th:nth-child(4), .userslist td:nth-child(4) { width: 15%; }
.userslist th:last-child { border-right: none }
.userslist tr:nth-child(even) { background-color: #EEE; }
.userData .userdetails { background-color: #dae0e8; padding: 1em 1em 0.5em 1.25em; border-radius: 1em; }
.userData .userdetails h1 { margin-top: 0.2em; font-size: 130%; }
.userData .userdetails label { color: #777; font-weight: bold; min-width: 2.75em; text-align:right; display: inline-block; }
.userData .message { padding: 0 1.25em; }
输出画面(Output screen)
祝您编程愉快!希望对您有所帮助!(Happy coding… Hope this helps!)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
Javascript CSS C# Knockout.js ASP.NET Dev 新闻 翻译