Very easy JS Bidirectional binding framework (II): Controller inheritance

Source: Internet
Author: User
Tags tagname

Original intention

The previous article has implemented two-way binding of the data, but the model control is the entire document. There is a need to have scope in actual project in order to do the split of the UI module.
In this article, we want to implement controller inheritance like Angularjs:
1. The model of the parent controller can be interviewed in the child controller
2. The model of the child controller does not affect the parent controller
3. The controller inheritance relationship is specified in HTML. Not specified in JS

Goal

In HTML, use the Isi-controller property to declare the controller:

<body>    <div isi-controller="Parentcontroller">        <input data-bind="name">        <div isi-controller="Subcontroller">            <input data-bind="name">        </div>    </div></Body 

Hopefully, the above input name is changed. The following changes, and the following changes, the above unchanged.


JS, define the controller with a function with the same name as above Isi-controller property value:

function ParentController() {    varnew Model();    model.set(‘name‘‘parent‘);}function ParentController() {    varnew Model();    model.set(‘name‘‘sub‘);}

To the user, just write these. It's over.

Implementation version Number 1

This version uses the simplest and most intuitive idea: the framework goes to the elements of $ (' [Isi-controller] '). And then to the elements to bind the listener, run the controller function
The code is listed first:
Index.html:

<html>  <head>    <title>Simple MVVM</title>    <script src="Js/parentcontroller.js"></script>    <script src="Js/subcontroller.js"></script>    <script src="Js/frame_v2.js"></script>  </head>  <body isi-controller="Parentcontroller">    <input type="text" data-bind="name">    <div isi-controller="Subcontroller">      <input type="text" data-bind="name">    </div>  </body></html>

Parentcontroller.js:

function ParentController() {    varnew Model();    model.set(‘name‘‘parent‘);}

Subcontroller.js:

function SubController() {    varnew Model();    model.set(‘name‘,‘sub‘);}

Frame_v2.js: (In contrast to the previous one, the main modification in the binding listener and the new model's own initiative)

varPubSub = ...//See previous articlevarModel = ...//See previous article//Listener capture view changes-publish Model.change eventvarChangehandler = function(event) {    vartarget = event.target, propname = Target.getattribute (' Data-bind ');if(PropName && propname!=="') {Pubsub.pub (' Model.change ', propname, Target.value); } event.stoppropagation ();}/ *-----------Init--------------* /Window.onload = function() {    /* First step: * Find controllers ' dom */    varControllerranges = Document.queryselectorall (' [Isi-controller] ');/* Second step: * Bind listeners for each controllers ' range, * View.change Event--and change each Controlle RS ' range * /     for(varI=0, Len=controllerranges.length; i<len; i++) {Controllerranges[i].addeventlistener (' Change ', Changehandler,false);//View.change Event ---Change View( function(index){Pubsub.sub (' View.change ', function(propname, newval) {                varelements = Controllerranges[index].queryselectorall (' [data-bind= '+ propname +'] '), TagName; for(varI=0, L=elements.length; i<l; i++) {tagName = Elements[i].tagname.tolowercase ();if(tagname===' input '|| tagname===' textarea '|| tagname===' SELECT ') {elements[i].value = newval; }Else{elements[i].innerhtml = newval;        }                }            });    }) (i); }/* Third step: * Execute each Controller function */     for(varI=0, Len=controllerranges.length; i<len; i++) {varControllername = Controllerranges[i].getattribute (' Isi-controller ');Eval(controllername+' () '); }}

Look at the effect:

Tragedy.

Did not implement the second intention: the child controller does not affect the parent controller.
How should the problem be solved?

Version number two, the child does not affect the parent

A careful look at the code, the reason for the failure is due to the scope of the View.change channel is problematic. Regardless of which model emits the View.change event, the view of the two controller changes.
Therefore, when we announce the View.change event, we publish a controller name more. So that when you receive view.change, you should not be able to modify HTML:

varfunction(controllerName) {    var model = {        controllerName:controllerName,        props: {},        function(propName, value) {            this.props[propName] = value;            pubsub.pub(‘view.change‘this//就是这里!

} }

When the new model is in the controller, be careful to initialize the controllers ' names in:
Parentcontroller.js:

function ParentController() {    varnew Model(‘ParentController‘);    model.set(‘name‘‘parent‘);}

When you finally receive the View.change channel message, infer the following controllername:

pubsub.sub(‘view.change‘function(propName, newVal, controllerName) {                ....                thisControllerName = controllerRanges[index].getAttribute(‘isi-controller‘),                if(thisControllerName !== controllerName)                    return;                ....}

Of course. The same is true when the listener publishes Model.change. To publish the controller name. The code will not be posted.


And look at the effect:

It's settled.

All code:
Github/victorisildur

Very easy JS Bidirectional binding framework (II): Controller inheritance

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.