Transferred from: http://www.cnblogs.com/jesse2013/p/a-sample-of-single-page-applicaton.html
Perhaps single page application is not a fashionable thing to do, like Gmail has been using this mode very early. The usual argument is that it greatly improves the responsiveness of the site by avoiding page refreshes, just as it does with desktop applications. Especially in today's mobile era, if a single-page program on the mobile device can have the same experience as the native app, perhaps we web developers should look forward to the popularization of this technology, so whether the front end or back end is our world Ah, Let those andrioid and iOS developers catch up with us! Okay, nonsense, we're going to start building a single-page Web site from 0, and we'll show you how the open source frameworks listed in our headline help us build quickly. The new technology is more, I also study, have insufficient place please haihan:)
Note: As this demo is for foreign colleagues to see, so the page content is in English, please forgive me. Poke here to see the online demo. Http://myspademo.cloudapp.net
Source Address: Https://github.com/jesselew/SpaDemo
Directory
- Requirements Introduction
- Single-page Program introduction
- Project Architecture
- Open Source Framework Introduction
- Bootstrap
- Requirejs
- Director
- Knockout
- Using Requirejs to implement remote template invocation
- A discussion of partial updates in rest
- Model Validation for WEB APIs
- Summary
Requirements Introduction
Our requirements are simple, through this single-page program to complete the management of the event, the following simple list of several requirements.
Functional Requirements
- Add Modify Event
- Event has opening and closed status, that is, the function of closing event is required.
- The Event List page can be filtered by status
- Closed event can no longer be modified
Non-functional requirements
- Reduce requests to the server as much as possible
- Data integrity (authentication)
- Authentication and authorization (the system will have at least 2 roles and have different permissions)
- Maintainability
Authentication and authorization This piece is not done temporarily, the back can continue to improve, verify that this piece is only done back-end, usually for security and user experience is required both back-end and front-end to achieve validation. I've uploaded this demo to Windows Azure, so let's get a feel for it. Http://myspademo.cloudapp.net
Single-page Program introduction
First of all, I think we can divide the response mode of the page into 3 phases:
1. The most traditional stage: everything has to be refreshed
In the most traditional Web site, the client sends a request to the server, and after the server responds, the generated HTML is returned to the client via response, so that one goes. The experience is, of course, the worst, and more needs to be handled for the server as well.
2. Page Local Refresh
This is what people think of when they fire up from Ajax. The data of a piece of the page can be displayed on the page after the page has been loaded by the client, and then a new request is made to take down the HTML code of a piece. There are two ways, one is the background directly to the HTML generated directly back, the other way is the server only return data, the client then spell HTML. When taking the second approach, someone might have used advanced templating techniques, and some might still be using powerful string stitching techniques. Anyway, we progress, the user can see the page first, and then a piece of slowly loading, the user feels cool, and no longer a blank in there turn ah turn ah.
3. Whole Station single page
The arrival of the single page of the whole site was first in 2005, and of course it was just a term. Specific examples, I first contact with the Gmail, of course, the simplest single page is actually very simple, such as a Q mailbox, the whole frame in the page, no matter how you point, it is not feel refreshed. Here's a brief talk about the advantages of this single page we're trying to achieve compared to a single page implemented with frame.
- A well-defined URL that is more user-friendly and a search engine.
- You can achieve a cohesive animation, which is especially important on mobile devices.
Page life cycle Comparison
Here is a picture from MSDN above the traditional page life cycle, the following is the life cycle of our single page program page. Let's take a look at the advantages and challenges that the page of this model brings to our users and developers.
Advantages
- A better user experience for users, especially on removable and touch-enabled devices
- For developers, after a good hierarchical architecture has been defined, the UI and data can be completely separated, as long as the data interface in the background does not change, the logic of the background can arbitrarily change the page does not affect the front-end display, and after the front-end MVVM framework, our front-end data can also be separated from UI completion.
Problem
- The biggest challenge is the JavaScript part, because all on one page, we need to deal with variable overrides, variable scopes, and for front-end developers the requirements will be higher
- For globalization, modules such as licensing need to be reconsidered and designed to better suit the development of this single-page program
Project Architecture
After stripping a picture, my picture has to be drawn with its coordination, no my handwriting style looks good, has the wood?
- Using knockout as the front-end MVVM framework
- To load a remote template with Requirejs
- Use director as the front-end route.
- Model data is directly interacting with the Web API, including authentication and authorization
- A template is a controller, and each template corresponds to an action
View Container
This is a client's template container, in the Requirejs of the base package, the first call to a template will go to the server to take, and then directly with the client.
Why is the template not directly used in HTML?
I have also thought of this problem, with pure HTML will not have to go to MVC that set of life cycle, the server pressure reduction is not small. But considering the authorization module and global resources in our view, it can be processed and returned directly on the server side. And I also stole a lazy, did not put these in the customer to achieve, we have good ideas to share?
Open Source Framework Introduction
With so many open source frameworks, what are they all about and how do they work? Here we have a little chat about these open-source frameworks.
Bootstrap
This thing I think a lot of people know, I will not say more. With it, we programmers do not need art and can make a very beautiful interface, although my demo is not very good-looking, but if it does not really know how many times ugly. It also has the Chinese version of the site: http://www.bootcss.com/
Director.js
This is a front-end route framework, what is a front-end route? If you go to see my demo, you will find that the URL is not as constant as a Q mailbox, we can still be like before every single function of a URL. For example:
- #/events/create
- #/events/all
- #/events/closed
- #/events/1
In addition to being friendly to the user, writing the code is more logical because the director binds a function for each URL, just like an action in MVC. When the user enters the corresponding URL, the corresponding function is triggered.
Here is a small example from the official homepage, so that you can use director at a glance.
Requirejs
I don't have to introduce you to this stuff, it has the ability to delay loading and avoid repeated loading, from the official definition: Requirejs is a JavaScript file and a module loader.
Knockout.js
This thing even if I want to introduce you or not few words can say the clear, specific you still refer to the source code bar. Or the uncle in the garden has translated an official tutorial, interested students can see. Anyway it's a JavaScript MVVM framework and of course there's a lot of this framework, Backbonejs, Breezejs, Durandal,emberjs,angular and so on, and I don't know all about it, So I can't tell you where their strengths and weaknesses are. The choice of knockout.js is due to the previous knowledge, good to start, and then the above 3 open source frameworks are all based on the MIT open source Agreement, so that we can use it for commercial development.
Using Requirejs to implement remote template invocation
It is not possible to load HTML templates directly with require, which has been said to be a JavaScript file and a module loader. So we need to use the Requirejs text plugin, so we can use it to load this. Https://github.com/requirejs/text
Download the text.js, put it directly in the root of our program, and then we can use the same method as loading JS to load the HTML code, in addition to our file location before adding a text! Outside
123 |
require([ ‘text!/template/createevent‘ ], function (template) { // 你在这里就可以拿到模板了。 }) |
A discussion of partial updates in rest
There are four types of HTTP verb we use:
We update the whole model by put. Of course, you can also change the following way, just update the field you want to update.
1234567891011121314 |
[HttpPut]
public void
Put(Event item)
{
var
newItem =
new
Event();
newItem.Id = item.Id;
// 在下面将你想要更新的值转到newItem下
newItem.Title = item.Title;
if
(!repository.Update(newItem))
{
throw
new
HttpResponseException(HttpStatusCode.NotFound);
}
}
|
Note: The URL of the Put method is only one (in the case we do not build other route), that is, we listed above the/api/events/{id}, and then the event object as the body passed. For example, in our demo, we have update operations, as well as "close" such operations, I think such operations are almost in every system will encounter, such operations will only update a field (here is the "status" column). So how do I build a put method to change this field? And the best way is I just pass the ID to the past.
With Google, I found something called Patch, which is also an HTTP verb, and it also provides update operations. But unlike put, patches allow only the fields you need to change to be uploaded to the server side.
1234567891011 |
var
obj = { Revision :
"2"
};
$.ajax({
url:
‘api/values/1‘
,
type:
‘PATCH‘
,
data: JSON.stringify(obj),
dataType:
‘json‘
,
contentType:
‘application/json‘
,
success:
function
(data) {
}
});
|
But in any case, I have no way of doing this, and once my entity object is added with some validation attribute such as required, those fields will all be assigned the default values. In the end I had to give up this practice.
Add a route to create two put methods
Another approach, which we implemented in our demo, is to add a route that implements two put methods in our Web API.
123456789101112131415 |
[Route(
"api/events/{id}/close"
)]
public
void
Put(
int
id)
{
var
item = repository.Get(id);
if
(item ==
null
)
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
item.Status = EventStatus.Closed;
if
(!repository.Update(item))
{
throw
new
HttpResponseException(HttpStatusCode.NotFound);
}
}
|
So when I submit it to api/events/3/close in a put way, our Web API executes the method above and closes our event.
Validation of the WEB API
Basically, no system can avoid dealing with validation, unless that system does not get the data from the user at all. The WEB API is validated in much the same way that we can still declare validation conditions in our model using the attribute method.
12345678910111213 |
public
class
Event
{
public
int
Id {
get
;
set
; }
[Required]
[MinLength(10)]
public
string
Title {
get
;
set
; }
public
string
Description {
get
;
set
; }
public
DateTime Start {
get
;
set
; }
public
DateTime End {
get
;
set
; }
[Required]
public
string
Owner {
get
;
set
; }
public
EventStatus Status {
get
;
set
; }
}
|
In the API method, we use Modelstate.isvalid to judge.
123456789101112 |
public
HttpResponseMessage Post(Event item)
{
if
(ModelState.IsValid)
{
// 保存操作
return
new
HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return
Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
|
Using AOP to implement validation
Or we can switch to the following to create a filter first.
1234567891011 |
public
class ValidateModelAttribute : ActionFilterAttribute
{
public
override
void
OnActionExecuting(HttpActionContext actionContext)
{
if
(!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
|
Go to post and put on the method above the label.
123456789 |
[httpput] [validatemodel" public void put (Event Item) {      If (!repository. Update (item)      {          throw new httpresponseexception (httpstatuscode.notfound);      } } |
We also need to register this filter in our webapiconfig.
1234567 |
public static class webapiconfig {      Public static void register (httpconfiguration config) { config. Filters.add ( new Validatemodelattribute ());      } } |
The front end gets this message and can be notified to the user. Of course, the final need to add front-end verification, can greatly improve the user experience and reduce the pressure on the server.
Summary
No summary, everybody scattered! I'm going to go to work by bike, what about you?
Bootstrap + requirejs+ director+ knockout + Web API = A trendy single-page program