What can the controllers of javascriptmvc do? It is a jquery plug-in factory. They can be used as traditional views, create paging controls or grids, or use them as traditional controllers, initialize controllers, and combine them with models. The Controller is quite helpful for organizing applications.
Controller provides many useful features, such:
- Create jquery plugin
- Automatic Binding
- Default settings
- Automatic decision
The following code creates a tooltip control. When the page is clicked, the elements are displayed:
$.fn.tooltip = function(){ var el = this[0]; $(document).click(function(ev){ if(ev.target !== el){ $(el).remove() } }) $(el).show(); return this;})
To use this control, you need to add an element on the page, and then use tooltip on it:
$("<div class='tooltip'>Some Info</div>") .appendTo(document.body) .tooltip()
However, there is a problem with the above Code, that is, many tooltip elements will be created, and they will be stored in the memory to occupy a lot of content, which will lead to performance problems. This is because the click handler will not be removed from the page, and a closure will always point to these elements.
In addition, this can easily cause errors. When an HTML element is removed from a page, jquery removes its related event processing, so developers do not have to worry about canceling event binding. However, event binding is not canceled for events other than elements, such as those in the document. In the MVC Architecture, the Controller listens to the view and view listen to the model. You will always listen to events outside the control element. For example, the nextprev plug-in mentioned in the previous section will listen to the update operation of the paginate model.
paginate.bind('updated.attr', function(){ self.find('.prev')[this.canPrev() ? 'addClass' : 'removeClass']('enabled') self.find('.next')[this.canNext() ? 'addClass' : 'removeClass']('enabled');})
However, they do not unbind from paginate. Forgetting to delete Event Handlers is a potential source of errors. However, neither tooltip nor nextprev will produce errors, but they will silently consume application performance. Fortunately, $. controller makes the work side simple and easy to manage. We can rewrite tooltip as follows:
$.Controller('Tooltip',{ init: function(){ this.element.show() }, "{document} click": function(el, ev){ if(ev.target !== this.element[0]){ this.element.remove() } }})
When the document is clicked or the element is removed from the Dom, $. Controller automatically unbinds the document click event. $. Controller is also bound to the paginate model of the nextprev control:
$. Controller ('nextprev ',{". next click ": function () {var paginate = This. options. paginate; paginate. ATTR ('offset', paginate. offset + paginate. limit );},". prev click ": function () {var paginate = This. options. paginate; paginate. ATTR ('offset', paginate. offset-paginate.limit);}, "{paginate} updated. ATTR ": function (EV, paginate) {This. find ('. prev') [paginate. canprev ()? 'Addclass': 'removeclass '] ('enabled') this. Find ('. next') [paginate. cannext ()? 'Addclass': 'removeclass '] ('enabled') ;}}) // create nextprev $ (' # pagebuttons'). nextprev ({paginate: New paginate ()})
If # pagebuttons is removed from the page, the nextprev control instance automatically unbinds the paginate model. Next we will discuss how $. controller works.
Overview
$. Controller inherits from $. Class and uses $. Controller (name, classproperties, instanceproperties) to create a controller class. parameters include the control name, static method, and instance method. The following describes how to create a list control that can be reused:
$.Controller("List", { defaults : {}},{ init : function(){ }, "li click" : function(){ }})
When a controller class is created, it creates a jquery helper method similar to the class name. The auxiliary method is mainly used to create a controller instance on the HTML element of the page. The name of the auxiliary method replaces some characters in the class name with underscores, for example$.Controller('App.FooBar')The auxiliary method name of is$(el).appfoobar()。
Controller instantiation
You can use new controller (element, options) to create a controller instance. The method includes two parameters: using the HTML element of the control and optional configuration items, for example:
new List($('ul#tasks'), {model : Task});
Of course, you can also use the jquery-assisted method to create a class instance:
$('ul#tasks').list({model : Task})
When a controller instance is created, the system calls the prototype method init:
this.elementPoint to the HTML element of the Controller;
this.optionsMerge the options passed to the constructor with the default options.
The following code retrieves task data from the model to update the controller and renders the page using the options template:
$.Controller("List", { defaults : { template: "items.ejs" }},{ init : function(){ this.element.html( this.options.template, this.options.model.findAll() ); }, "li click" : function(){ }})
We can use the list controller like this. The code is quite simple. If we do not provide a template, the list will use "items. ejs" by default ".
$('#tasks').list({model: Task, template: "tasks.ejs"});$('#users').list({model: User, template: "users.ejs"})
Event binding
$. A powerful feature of controller is event binding and unbinding. When a controller is created, it queries the action method. The action method looks like the event processing method, for example, "Li click ". The actions usedjQuery.bindOrJquery. Delegate implements binding. When the controller is destroyed, the HTML element of the Controller will be removed from the page, or the events will be unbound using the destroy method of the Controller to save memory. This is an example of action, which describes the objects they listen:
"li click"-The Li or Li internal element in the element where the controller is located is clicked.
"mousemove"-Execute mousemoves for the element where the controller is located.
"{window} click"-The window or internal object is clicked.
The action method is called back by the HTML element or the object where the event occurs. For example:
"li click": function( el, ev ) { assertEqual(el[0].nodeName, "li" ) assertEqual(ev.type, "click")}
Templated action
$. Controller supports action templatification and can be used to bind other objects, custom events, or custom selectors. $. Controller uses the options value or window to replace action. For example:
$. Controller ("menu", {"Li {openevent}": function () {// event processing}); // create a menu, set the Click Event $ ("# clickmenu") of Li "). menu ({openevent: 'click'}); // create a menu and set the Li mouseenter event $ ("# hovermenu "). menu ({openevent: 'mouseenter '});
We can further customize the element labels:
$. Controller ("menu", {defaults: {menutag: "Li" }},{ "{menutag} {openevent}": function () {// event processing }});
$("#divMenu").menu({menuTag : "div", openEvent: 'click'})
Templated action allows you to bind elements or objects outside the controller. For example, the task model in the previous section triggers the "created" event during the creation process. We can add a listener for the task created event to the list, as shown below:
$.Controller("List", { defaults : { template: "items.ejs" }},{ init : function(){ this.element.html( this.options.template, this.options.model.findAll() ); }, "{Task} created" : function(Task, ev, newTask){ this.element.append(this.options.template, [newTask]) }})
We can also model the model so that we can set the model in options to support any model:
$. Controller ("list", {defaults: {template: "items. ejs ", model: NULL },{ init: function () {this.element.html (this. options. template, this. options. model. findall () ;}, "{model} created": function (model, Ev, newitem) {This. element. append (this. options. template, [newitem])}); // create tasks list $ ('# tasks '). list ({model: task, template: "tasks. ejs "});
Set all functions-an abstract crud list
Now we have added support for update and destroyed for the list:
"{Model} updated": function (model, Ev, updateditem) {// use updateditem to update Li}, "{model} destroyed": function (model, Ev, destroyeditem) {// use destroyeditem to Remove Li}
We will find a problem. We need to find elements that represent a specific model instance, so we need to mark the elements as all of a mode instance. Fortunately, $. Model and $. View simplify the above work. In the ejs view, you only need to simply write the model instance to the element by using the model instance Tag Element.
<% for(var i =0 ; i < this.length; i++){ %> <% var task = this[i]; %> <li <%= task %> > <%= task.name %> </li><% } %>
Tasks. ejs traverses the task list, creates a Li for each task, and uses<LI <% = task %> indicates that the task is in the jquery data of the element. You can use modelinstance. Elements ([Context]) to obtain the HTML element representing it later through the model instance.
$. Controller ("list", {defaults: {template: "items. ejs ", model: NULL },{ init: function () {this.element.html (this. options. template, this. options. model. findall () ;}, "{model} created": function (model, Ev, newitem) {This. element. append (this. options. template, [newitem])}, "{model} updated": function (model, Ev, updateditem) {updateditem. elements (this. element ). replacewith (this. options. template, [updateditem])}, "{model} destroyed": function (model, Ev, destroyeditem) {destroyeditem. elements (this. element ). remove ()}); // create tasks list $ ('# tasks '). list ({model: task, template: "tasks. ejs "});
Through the above introduction, you must have mastered how to use javascriptmvc to create abstract, reusable, and memory-saving plug-ins.
Javascriptmvc tutorial directory