Document directory
- Model
- View
- Template
- Asynchronous task
Composition
This is a very common Weibo list page, similar to Sina Weibo. Last weekend, a total of five objects were used to generate 400 lines of code, and a code organization mode was developed.
The code for easy task completion consists of four elements:
Elements |
Composition |
Model |
Reply, forward |
View |
Commenteditor, replylist, and forwardlist |
Template |
Jquery. tmpl |
Asynchronous task |
Jquery. Deferred |
Division Introduction Model
A model is only related to data. It can generate, filter, store, and verify data.
For example, when the message model calls the Save method, it only receives JSON parameters and returns only one asynchronous task. In actual processing, synchronous or asynchronous return results are not important.
The reason for this verification is that it is an open object and the last threshold for interaction with the server.
In addition, it does not handle the verification failure itself-it is selectively processed by the view when calling, a message prompt may pop up or ignore it directly and try again.
// Message Model VaR reply = {cache :{}, // {sourceid: ID, page_size: 10, page_num: 1} fetch: function (data) {return $. post ('/ajax/blog/reply/list', data || {}). success (function (RESP) {resp. OK & resp. list & $. each (resp. list, function (K, v) {return reply. cache [v. id] = V ;}) ;}, // filter ('name', 'King') filter: function (prop, Val) {return $. grep (this. cache, function (r) {return R [prop] = Val}) ;}, // {content: 'Whatever you want to say ', sourceid: 1001} create: function (data) {// promise var DFD = $. deferred (), now = $. now (); If (now-this. create. time stamp)/1000
View
A view is a visible part of a browser page. Each view object contains an associated jquery object as an attribute (instance. $ El), similar to the DOM container in the UI component.
There are two ways to make the view consistent:
- The render method is used to obtain data from the model and render the data to the HTML page according to the defined template.
- The activate method is used to activate a view and bind related DOM events. All events are delegated to $ El at most.
In this example, commenteditor is the parent view, and replylist and forwardlist are two child views that are mutually exclusive. The Parent and Child views store references to each other.
// Return list view var replylist = function (options) {var opt = This. opt = $. extend ({El: '', parent: NULL}, options ||{}); this. parent = OPT. parent; this. $ El = $ (OPT. el); this. activate () ;}; replylist. prototype = {render: function () {var self = This; reply. fetch ({page_size: 10, page_num: 1, sourceid: Self. parent. getblogid ()}). done (function (data) {self.$el.html (self. $ list = $. tmpl (tpl_reply_list, data) ;}); return self ;}, activate: function () {This. $ el. delegate ('a. del ', $. proxy (this. del, this ))}//...} // commenteditor in the comment editor view. prototype = {activate: function () {This. $ el. delegate ('a. save ', $. proxy (this. save, this)}, save: function () {var self = This, Data = {content: Self. getcontent (), sourceid: Self. getblogid ()}; var task_r = reply. create (data); var task_f = forward. create (data); // forward and comments at the same time $. when (task_r, task_f ). then (function (T1, T2) {// save successfully, update view or close}, function (data) {// model verification error, or remote server error sys.info (data. message, Data. type) ;}); return self ;}, switchview: function (type) {// switch the subview var view_opt = {El: This. $ sublist. empty (), parent: This}; If (type = 'reply') {$ label. show (); this. $ submit. val ('comments'); this. sublist = new replylist (view_opt ). render ();} else {$ label. hide (); this. $ submit. val ('forwarder '); this. sublist = new forwardlist (view_opt ). render ();}}//...}
Template
The template can eliminate tedious and ugly String concatenation. Its function is to generate HTML fragments directly from JS objects.
The template can directly traverse objects and apply predefined functions to format some data, such as the time function nicetime:
// Reply list template var tpl_reply_list = '<ul class = "UI-reply-list" >\{{ each list }\< Li data-id = "$ {ID} ">\< a class =" name "href ="/$ {userid} ">$ {name }: </a >\< P >$ {content} </P >\< time pubdate >$ {nicetime (timestamp )} </time> <a class = "Del" href = "javascript :; "> Delete </a >\</Li >\{{/each }}\</ul> ';
Asynchronous task
The literal translation of a deferred object is a delayed object, but it is more appropriate to understand it as an asynchronous task. Asynchronous tasks can eliminate multi-layer nested callbacks, making code writing and reading more convenient.
From the above model and view code, we can see that after an asynchronous task is used, the Code becomes more flat.
$. The deferred method creates a two-way task queue: The success callback function queue and the Failure callback function queue. The task status is divided into two types: success and failure, you can use isresolved or isrejected to check the current status of the task, and use resolve or reject to modify the status of the task.
The promise method returns the read-only copy of the task, which cannot be changed. There is no doubt that the model should always return only the promise object. (Note: Read-Only copies can still be returned again by calling the promise method)
In the reply. Create method, you can better process custom asynchronous tasks rather than directly returning native Ajax asynchronous tasks:
// Var DFD = $. deferred (); $. post ('/ajax/blog/reply/create', data ). success (function (JSON) {If (JSON & JSON. OK) {DFD. resolve (JSON. list);} else {DFD. reject ({message: JSON. message | 'retrieval failed', type: 'error '});}}). fail (function () {DFD. reject ({message: 'service temporarily unavailable ', type: 'error '})});
Objective and conclusion
Why is this split?
Gains: maintainability, clear API calls, elimination of IF Statements at or above the second layer, elimination of callback statements at or above the second layer, and control each function within 20 rows.
Result: No code is repeated, and all functions are packaged.