Used to be silently look at the garden articles, wretched point of praise, today also share their own JS implementation of a simple MVVM framework.
Initially only to do automatic binding events, followed by reference to learn the vue,knouckout and argular implementation, as well as some of the experience of doing WPF, adding a property binding, and today, a little tidying up, complete some of the functions, the code submitted to the code cloud: https:// Gitee.com/zlj_fy/simple-mvvm
Let's take a brief introduction to the following usage:
1 <formclass= "Form-horizontal"role= "form"Data-context= "TestController">2 <Divclass= "Form-group">3 <legend>Form Title</legend>4 </Div>5 <Divclass= "Form-group">6 <Divclass= "Col-sm-6 col-sm-offset-2">7 <inputtype= "text"class= "Form-control"Bind-val= "Age,format=format"style= "margin:5px 0" />8 <inputtype= "text"class= "Form-control"Bind-val= "desc"style= "margin:5px 0" />9 <inputtype= "Range"min= "Ten"Max= "+"Bind-val= "Age"Step= "Ten"class= "Form-control"style= "margin:5px 0" />Ten <inputtype= "button"class= "Btn btn-primary"value= "Update"style= "margin:5px 0"On-click= "Update" /> One </Div> A </Div> - </form> - the <Script> - varTestController= { - data: { - Name:'xiaoming', + Age :3, - desc:function() { + returnthis.name+ 'likes looking little movie. He should take care of the His body' A } at }, - format:function(val) { - returnVal+ 'years' - }, - Update:function() { - This. Name= 'This is a test' in This. Age= - - } to } + $('Body'). Controller () - </Script>
You first define a controller, either a JSON object or a function, and then bind the controller to all the elements underneath that node by defining the data-context= "[controller name]" on the top-level element. If a nested controller exists for the descendant of an element, the element that is located below the child element scope points to the child controller.
1. Monitoring properties and complex properties
All attributes must be defined under the data node, and if the attributes inside are defined as function, they are considered to be complex properties (such as DESC), the complex property is read-only, and the re-assignment will prompt an error.
Bind to a format on an HTML element: "{attribute name, fomat=[controller Method]}", property name supports nested properties, For example (a.b); Property names do not support expressions, consider that it is not necessary to use complex attributes can be replaced, the current disadvantage is that the business complex can result in a large number of complex properties; the right side of the property name is an optional parameter, currently only format, that is, the property is displayed on the HTML conversion method.
2. Directives
Binding instruction syntax is the form of the bind-{Directive}, and now only implements the val,attr,text,html,template, in fact, it can be seen that the first 4 are simply encapsulated Jqeury method, template is used to Jquery-tmpl plug-in implementation , if you need more instructions, you can expand it yourself, just implement the Init initial load method (receiving the current observer parameter), and the Update method (parameter description: The corresponding jquery element, the latest value, the current controller instance), and if it is an extension of an existing instruction, The default overrides the original. As follows:
1 $.controller.adddirective ("Val", {
2Init:function(Observer) {3 if(Observer. $ele. Is (' Input,select ')) {4 //Monitoring onchange Events5Observer. $ele. On (' Input PropertyChange ',function () {6 varnewval = $ ( This). Val ()7 Observer.writevalue (newval)8 })9 }Ten }, OneUpdatefunction($ele, newval, controller) { A$ele. Val &&$ele. Val (newval) - } -})
3. Events
Binding event Syntax: on-{event}= "{Controller method},type=on/one", the controller method to the right is an optional parameter, currently only the binding type On/one, the default is on; The Controller method receives two parameters, one is to set the initial parameters on the element corresponding to the event. One is the event argument;
1 < type= "button" class= "btn btn-primary" data-page= "1" on-click= "Refesh"> query </button>
4. Methods
Directly using the This property name, you can directly access the properties under the corresponding data node.
5. Hooks
Init and Created,init are the parameters that can be initialized on this method before the DOM is compiled after listening for all the attributes; created is after the DOM element is compiled.
Where the controller implements the Extend inheritance method by default and can inherit from another controller, it must be used in the Init method. At present you can also use the method of prototype inheritance to achieve.
1 function () {2 This . Extend (Pagecontroller) 3 }, 4 function () {5 // TODO 6 },
6. Expansion
I believe that when you do the project will certainly have a common component, then you can expand as follows, the default corresponding components are mounted to all the controller example below, you can directly call in the corresponding method: This.http.post ();
One suggestion, however, is to try to unify the scope of the callback method to the controller so that the development does not always have a scope problem.
1 $.controller.extend ({2 utils:utils,3 notify: $.notify, 4 modal: $.modal,5 http: $.http,6 alert: $. Alert7
7. Principle and Code analysis (to be continued ...) )
The entire JS code is only more than 300 lines, so the implementation of the relatively simple, there are many aspects are not considered, there are some features are want to achieve but not to do,
Array change detection is not currently supported, and the associated DOM is partially updated.
Hey, blogging is a good time to go to bed ...
JS to implement a simple MVVM framework