Design and implementation of the front-end MVVM Framework (i)
Recently took some time to get a DOM modular template engine, but now this is all in MVVM, and simply want to build a wheel to write a simple MVVM framework
Reference to the natural or from the United States of Avalon began, I remember last June wrote a series of Avalon source analysis, but then 0.7 version, not sound enough, now is much better
The framework is geared towards a single area, providing a solution, so what can we do with the front-end MVVM that brings us convenience?
- Separation of attention points
- Manipulating data is manipulating the DOM
- Dynamic templates
The separation of concerns is the same as MVVM, the manipulation of data, the manipulation of the DOM, is the result of accessors in the VM, and the dynamic template is a process binding implementation.
There's too much discussion about mv*, not here, and our focus is on analyzing How to implement the front-end MVMM framework .
Avalon Address Https://github.com/RubyLouvre/avalon
What do you need to learn about MVVM first?
1. JavaScript Language Basics (scopes, prototype chains, closures, etc.)
2. Simple design mode, basic data structure
3. Read or write jquery source code
Why do you say that, because Avalon is the complex of these things!
I was based on the model of Avalon, according to the author is the idea of imitation, of course, Avalon code has more than 4,000 lines, novice if to learn the estimate can not, also powerless
Why is it? Simply say the means of implementation a bit different, write the code a bit wild (please forgive me I do not know how to describe), but the user experience is good!
A simple look at the code structure
<div ms-controller= "box" > <div style= "background: #a9ea00;" Ms-css-width= "W" ms-click= "click" ></ Div> <p>{{w}}p> </div> <script> function(VM) { VM.W = +; function() {VM.W = parsefloat (VM.W) + ten; }}) </script>
For this code structure, we need to understand:
1: Why to customize a lot of tags ( declarative binding )
This is the primal meaning of MVVM, the separation of data logic. Performance is the data JS logic code HTMLCSS Show
So again the HTML structure is a natural thing, if the HTML is generated with JS, it is not the same as MVVM
Why don't you need to manipulate the DOM inside 2:avalon.define?
In MVVM, the data is the core, because the two-way binding between the VM and V, manipulating the data in the VM (which can only be a monitoring attribute), synchronizes to the DOM, and we monitor the user's changes to the DOM through DOM events and synchronize to the VM.
In this chapter we will implement the first step: to set up a basic hierarchical structure, to implement a two-way notification mechanism
The first version of the implementation: 300 lines of code, please compare the analysis to see source Https://github.com/JsAaron/aaMVVM
For the above 2 questions, let's see how we can manipulate the data and manipulate the DOM.
Simple to say that the implementation is the idea: we can down git aamvvm control, than the original 4000 lines of code more friendly!
We know that in MVVM, M is just a passer-by, and it fits into the VM (ViewModel) with other things that represent business status. ViewModel is a collection of States, and of course telework monitors a large number of callbacks
So ViewModel is carrying almost all the functions, in Avalon ViewModel contains all the data and methods of definition, communication V and M, play the role of the connecting link ~
How do view models relate to data and views?
The properties and methods in the VM defined by Avalon.define are mapped to the tags in the corresponding HTML structure, so changing the DOM associated with the data in the VM will automatically refresh
Analysis under
VM.W = 100
When the data of the model is changed to 100, the width of the corresponding view div is 100, the text is <p>100</p>, and the 2 mapping actions associated with the data in the same controller will be modified.
One is a CSS operation, one is text assignment
From this operation we can venture to speculate that there should be a list in the VM.V, which records the corresponding mapping operation (multiple) under the current controller.
To implement the set and Get methods, Avalon is similar to Emberjs, using the Object.defineproperty
I use the simplest code to simulate the implementation of
<! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 transitional//en" "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "><ptml xmlns=" http://www.w3.org/1999/xhtml "><pead> <title> test vm</title> <meta http-equiv= "Content-type" content= "text/html; Charset=utf-8 "/> <meta http-equiv=" x-ua-compatible "content=" Ie=emulateie7 "/></pead><body> <div id= ' box ' ao-controller= "box" > <div id= ' aa-attr ' style= "background: #a9ea00; width:100px;height:100px;" Ao-css-width= "W" ao-click= ' click ' ></div> <p id= ' aa-text ' >{{w}}</p></div> <script> var vm = {} var bindings = {W:function (value) {if (value) {document.getElementById (' aa-attr '). Style.width = Val UE + ' px '; } else {return document.getElementById (' aa-attr '). Style.width; }}} var access = function (NewValue) {if (newvalue) {//set bindings[' W '] (newvalue);} else {//get return bindi ngs[' W '] ();} } object.definepropeRty (VM, ' W ', {get:access,set:access,enumerable:true,configurable:true}) VM.W = 300//Set Element.style.width = = Alert (VM.W) </script></body></ptml>
Other words
VM.W = 100 that is to modify the style also to modify P, is a one-to-many association
So in Avalon, for each monitoring attribute, a set and get access controller will be generated, so there will be an access controller for each monitoring property.
Accessor[subscribers] = []//subscriber array, such stuff to store dependencies associated with it
When we trigger VM.W = 100, it triggers the W:set method, takes out the dependencies in Accessor[subscribers], and executes each execution, thus implementing the dependency
The corresponding method: automatically updates its own dependencies
notifies subscribers who rely on this accessor to update their own function notifysubscribers (accessor) { var list =if (list && var args = [].slice.call (arguments, 1 for(var i = list.length, fn; fn = list[--var el = fn.element fn. Handler (fn.evaluator.apply (0, Fn.args | | []), El, fn) }}}
The above is just a simple idea, the real realization of the time really to achieve the framework of chatty, consider the problem is not so simple thing
1 How the framework interprets declarative binding syntax
2 How to generate a corresponding processing handle for parsed syntax
3 How the user defines how the VM model is generated
4 How to collect these dependencies
5 How to automatically update dependent mappings
JS Architecture design Mode--front-end MVVM framework design and implementation (I.)