Javascript MVC learning notes (2) controller and status, javascriptmvc

Source: Internet
Author: User

Javascript MVC learning notes (2) controller and status, javascriptmvc

Enter the second part today: controller.

Controller and status

From the past development experience, we have stored the status in the server session or local cookie, but Javascript applications are often restricted to single pages, therefore, we can save the status in the memory of the client. Saving in memory also means faster interface response.

In MVC, the status is stored in the controller, and the Controller is equivalent to the link between the view and model in the application.When loading a page, the Controller binds the event handler to the view and processes the callback in a timely manner, as well as the necessary connection with the model.

The Controller is modular and very independent. Ideally, no global variables should be defined, but completely decoupled functional components. Therefore, we put the Controller in an anonymous function that is processed immediately and pass global parameters in the module mode to avoid traversing the scope when accessing global variables internally, it also clearly shows the global variables used by this module.

(Function ($) {var mod ={}; // change the context of the parameter and execute mod immediately. load = function (func) {$ ($. proxy (func, this) ;}; // click the event mod. assetsClick = function () {// process click console. log ("click! ");} // Call the load method mod. load (function () {// Add a click event for the element this. view = $ ("# view"); this. view. find (". assets "). click ($. proxy (this. assetsClick, this) ;};}( jQuery );

Assume that the page contains the following elements:

<Div id = "view"> <button class = "assets"> buttons </button> </div>

After clicking the button, "click" will be output, which also implies the connection between the Controller and the view. In fact, this part of the book is about how to save the status in the controller, different views are changed based on different states.

(Note) jQuery. proxy (method, context)

$. The proxy method is the proxy method in jQuery. It receives two parameters and returns a new method, which always keeps the context.
For example, in the button listening:

$ ("# Btn"). click (function () {// here this represents the button });
$ ("# Btn"). click ($. proxy (function () {// here this represents window}, window ););
(Annotated) Abstract warehouse picking

Now, the controller is abstracted into a database and some new methods are added so that it can be reused in external or other modules.

(Function ($, exports) {// if parameters are passed through the constructor, call the include method var mod = function (primary des) {if (primary des) {this. include (includes) ;}}; // modify the prototype Object Name (easy to call) mod. fn = mod. prototype; // define your own proxy method. The context always points to the Controller's own mod. fn. proxy = function (func) {return $. proxy (func, this) ;}; // execute the function mod immediately. fn. load = function (func) {$ (this. proxy (func) ;}; // Add method mod for the constructor. fn. include = function (ob) {$. extend (this, ob) ;}; // exposes the constructor to the global environment. You can also access exports. controller = mod;}) (jQuery, window );

When you need a Controller elsewhere, you can call the Controller:

(Function ($, Controller) {// create the Controller var mod = new Controller (); // change the class name mod of the view. toggleClass = function (e) {// The toggleClass method in jQuery indicates that if this class name exists, it is deleted. If this class name does not exist, add this. view. toggleClass ("over");} // execute mod immediately after the page is loaded. load (function () {// bind the page element and add the listener this. view = $ ("# view"); this. view. mouseover (this. proxy (this. toggleClass); this. view. mouseout (this. proxy (this. toggleClass);} (jQuery, Controller)

In the above usage, the method called immediately through the anonymous function is not loaded after the DOM is loaded, but before the DOM is generated, however, the load method of the controller performs callback only after the page document is loaded. We can further rewrite the controller and load it to the Controller after DOM is generated.

// Define a global object var exports = this; (function ($) {var mod ={}; // provides a create method to generate the Controller mod. create = function (DES) {// result is returned by the create method. A controller var result = function () {// call the initialization method this when creating a controller instance. init. apply (this, arguments);} result. fn = result. prototype; result. fn. init = function () {}; result. proxy = function (func) {return $. proxy (func, this) ;}; result. fn. proxy = result. proxy; result. include = function (ob) {$. extend (this. fn, ob) ;}; result. extend = function (ob) {$. extend (this, ob) ;}; if (includes) {result. include (regiondes) ;}return result ;}; exports. controller = mod;}) (jQuery );

When creating a controller, you must manually specify the init method and add a listener to the dom element in the init method:

$ (Function () {// create the Controller var ToggleView = Controller. create ({init: function (view) {this. view = $ (view); this. view. mouseover (this. proxy (this. toggleClass); this. view. mouseout (this. proxy (this. toggleClass);}, toggleClass: function () {this. view. toggleClass ("over") ;}}); // create a controller instance new ToggleView ("# view ");});

When creating an instance, the init event will be triggered in the constructor. In addition, the view will be passed into the Controller Based on the instantiation, instead of being written to the Controller, we can reuse the Controller to different elements while keeping the code shortest.

Access View

A common mode is that a view corresponds to a controller, With a view containing an Id, while a view using a view in a controller uses a class, which does not conflict with other view elements, for exampleToggleViewThe element with the Id of view is input, so the elements in the view are accessed using the class name.

init: function(view){    this.view = $(view);    this.form = this.view.find(".form");}

However, this means that there are many selectors in the Controller and we need to constantly search for the DOM. We can create a space in the Controller to store the ing table from the selector to the variable:

elements: {    "form.searchForm": "searchForm",    "form input[type=text]": "searchInput"}

With such a ing table, the Controller attribute name (such as searchForm) can correspond to the specific element (the form class name is searchForm, and create them when the controller is instantiated:

$ (Function ($) {exports. searchView = Controller. elements in create ({// view use the class name to search for elements: {"input [type = search]": "searchInput", "form": "searchForm"}, init: function (element) {// obtain the view element this. el = $ (element); // create Attributes Based on the ing table this. refreshElements (); // Add listeners for the element. this. searchForm. submit (this. proxy (this. search) ;}, // event processing function search: function (e) {console. log ("Searching", this. searchInput. val () ;}, // specifies the context as the view element $: function (selector) {return $ (selector, this. el) ;}, // create the refreshElements: function () {for (var key in this. elements) {// key is the selector name, and the value is the attribute name this [this. elements [key] = this. $ (key) ;}}); // specify new SearchView ("# users") with the id of the view ");});
State Machine

A state machine is short for a finite state machine. It consists of two parts: State and converter. It has only one active state, but also contains many inactive states. The status converter is called when the active status switches between them.

For example, there are many views in the application, and their display is independent of each other. One view is used to display contacts, and the other view is used to edit contacts. These two views must be mutually exclusive, one of them must be hidden. This scenario is very suitable for introducing the state machine, because it ensures that only one of them is active at each moment.

First, let's take a look at the state machine idea. We construct a state machine:

Var StateMachine = function () {}; StateMachine. fn = StateMechine. prototype; StateMachine. fn. bind = function () {if (! This. o) {this. o =$ ({}) ;}// bind custom event this. o. bind. apply (this. o, arguments);} StateMachine. fn. trigger = function () {if (! This. o) {this. o =$ ({}) ;}// triggers the custom event this. o. trigger. apply (this. o, arguments);} StateMechine. fn. add = function (controller) {// bind a custom event to the state machine. this. bind ("change", function (e, current) {if (controller = current) {controller. activate ();} else {controller. deactivate () ;}}); // create an activation method controller for the controller. active = $. proxy (function () {this. trigger ("change", controller) ;}, this );}
(Note) custom events in jQuery

The above Code focuses on bind and trigger. In jQuery, you can use these two methods to easily implement custom events:

Var $ obj =$ ({}); $ obj. bind ("myEvent", function () {console. log ("Custom Event") ;}; $ obj. trigger ("myEvent"); // "Custom Event"

Bind indicates binding, trigger indicates triggering, and you only need a jQuery object. Therefore, an empty object is created above and $ is encapsulated as a jQuery object.

(Annotated)

The add () method of this state machine adds the incoming controller to the State List and binds o in the state machine to a custom change event (add one to bind one ), create an active () function. When the Controller calls active () and triggers all change events, All controllers except the called controller will execute the activate method will execute the deactivate method:

// Controller 1var con1 = {activate: function () {console. log ("con1 activate") ;}, deactivate: function () {console. log ("con1 deactivate") ;}}; // controller 2var con2 = {activate: function () {console. log ("con2 activate") ;}, deactivate: function () {console. log ("con2 deactivate") ;}}; var sm = new StateMachine (); sm. add (con1); sm. add (con2); con1.active (); // output "con1 activate" and "con2 deactivate"

Of course, it can also be triggered directly through the state machine.

sm.trigger("change", con1);

Through the switching status of the state machine, we can change the view with the Controller. When con1 is activated, a view is displayed; otherwise, another view is displayed when con2 is activated; otherwise, the view is hidden. In this way, views can be switched based on different states.

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.