Js implements a simple MVVM framework example, jsmvvm framework
I used to read the articles in the garden silently in the past. I would like to share my simple mvvm framework implemented in js today.
At first, I only bound events automatically. Later I learned how to implement vue, knouckout, and argular, and added property binding based on my own WPF experience, today, I made a little arrangement, improved some of the functions, the Code submitted to the Code cloud: https://gitee.com/zlj_fy/Simple-MVVM
First, we will briefly introduce the usage:
<Form class = "form-horizontal" role = "form" data-context = "TestController"> <div class = "form-group"> <legend> Form title </legend> </div> <div class = "form-group"> <div class = "col-sm-6 col-sm-offset-2"> <input type = "text" class = "form-control" bind- val = "age, format = format "style =" margin: 5 p x 0 "/> <input type =" text "class =" form-control "bind-val =" desc "style =" margin: 5 p x 0 "/> <input type =" range "min =" 10 "max =" 300 "bind-val =" age "step =" 10 "class =" form -control "style =" margin: 5 p x 0 "/> <input type =" button "class =" btn-primary "value =" Update "style =" margin: 5 p x 0 "on-click =" update "/> </div> </form> <script> var TestController = {data: {name: 'xiaoming', age: 3, desc: function () {return this. name + 'likes looking little movie. he shoshould take care of his body '}}, format: function (val) {return val + 'Year'}, update: function () {this. name = 'this is a test' this. age = 18 }}$ ('body '). controller () </script>
First, define a controller, which can be a json object or a function, then define data-context = "[controller name]" in the top-level element to bind the Controller to all elements under the node. If the child of an element has a nested Controller, the sub-element scope of the element to be located points to the sub-Controller.
1. Monitoring attributes and complex attributes
All attributes must be defined under the data Node. If the attribute is defined as a function, it is regarded as a complex attribute (such as desc), and the complex attribute is read-only. If you assign a value again, an error is prompted.
Format bound to html elements: "{attribute name, fomat = [Controller method]}". Attribute names support nested attributes, such as (. b) Attribute names do not support expressions. Considering the fact that they are not necessary, they can be replaced by complex attributes. The current disadvantage is that complicated businesses may cause a large number of complex attributes; the right side of the property name is an optional parameter. Currently, only format is available, that is, the conversion method for displaying the property in html.
2. Commands
The bind command syntax is in the form of bind-{command}. Currently, only val, attr, text, html, and template are implemented. In fact, we can see that the preceding four methods only encapsulate the jqeury method, template is implemented using the jquery-tmpl plug-in. If you need more commands, you can expand it by yourself. You only need to implement the init initial loading method (receiving the current observer parameter ), and the update method (parameter description: The corresponding jquery element, the latest value, the current controller instance). If it is to extend the existing commands, it will overwrite the original by default. As follows:
$. Controller. addDirective ("val", {init: function (observer) {if (observer. $ ele. is ('input, select') {// listens to the onchange event observer. $ ele. on ('input propertychang', function () {var newVal = $ (this ). val () observer. writeValue (newVal)}) }}, update: function ($ ele, newVal, controller) {$ ele. val & $ ele. val (newVal )}})
3. Events
Binding event Syntax: on-{event }= "{Controller Method}, type = on/one". The right side of the Controller method is an optional parameter. Currently, only the binding type on/one is available, the default value is on. The Controller method receives two parameters. One is to set the initial parameter on the element of the corresponding event, and the other is the event parameter;
<Button type = "button" class = "btn-primary" data-page = "1" on-click = "refesh"> query </button>
4. Method
Directly use this. attribute name to directly access the attributes of the corresponding data node.
5. Hooks
Init and created. init is a parameter that can be initialized in this method before listening to all attributes and compiling dom. created is after compiling dom elements.
The Controller implements the extend Inheritance Method by default. It can inherit from another controller and must be used in the init method. You can also implement it by yourself using prototype inheritance.
init: function () { this.extend(PageController) }, created: function () { //TODO },
6. Expansion
I believe that there will certainly be a set of public components when you are working on the project, so you can extend it as below. By default, the corresponding components are mounted to all controllers, you can call this directly in the corresponding method. http. post ();
However, there is a suggestion that the scope of the callback method should be pointed to the Controller as much as possible, so that the development will not always have scope problems.
$.controller.extend({ utils: utils, notify: $.notify, modal: $.modal, http: $.http, alert: $.alert })
7. Principles and code analysis (To be continued ...)
The total JavaScript code volume is only over 300 lines, so the implementation is relatively simple, there are many aspects that are not taken into account, there are some features that are intended to be implemented but not done, currently, array change detection and partial update related dom are not supported.
The above js Implementation of a simple MVVM framework example is all the content shared by the small Editor. I hope to give you a reference and support for the customer's house.