avalon你们可能不熟悉,可是Knockout估计或多或少听过用过,那么说说KO的几个概念css
本章主要提到 监控属于 与 依赖跟踪(后更名叫计算属性)git
监控顾名思义,监听着你设定目标的变化,换句话说可以通知订阅者它的改变以及自动探测到相关的依赖。github
计算属性,就是依赖监控属性变化而自动调用处理更新数组
KO的一个例子ruby
若是你已经有了监控属性firstName和lastName,你想显示全称怎么办? 这就须要用到依赖监控属性了 – 这些函数是一个或多个监控属性, 若是他们的依赖对象改变,他们会自动跟着改变。mvvm
例如,下面的view model,函数
var viewModel = { firstName: ko.observable('Bob'), lastName: ko.observable('Smith') };
… 你能够添加一个依赖监控属性来返回姓名全称:this
viewModel.fullName = ko.dependentObservable(function () { return this.firstName() + " " + this.lastName(); }, viewModel);
而且绑定到UI的元素上,例如:编码
The name is <span data-bind="text: fullName"></span>
… 无论firstName仍是lastName改变,全称fullName都会自动更新(无论谁改变,执行函数都会调用一次,无论改变成什么,他的值都会更新到UI或者其余依赖监控属性上)spa
OK
KO是怎么实现双向机制的呢?
avalon实现双向绑定跟ko的实现其实大同小异,可是ko的实现异常的复杂,avalon则清晰不少
上列子,而后分析
HTML结构
<div id='box' ms-controller="box"> <div style=" background: #a9ea00;" ms-css-width="w" ms-css-height="h" ms-click="click"></div> <p>{{ w }} x {{ h }}</p> <p>W: <input type="text" ms-model="w" data-event="change"/></p> <p>H: <input type="text" ms-model="h" /></p> </div>
JS
avalon.define("box", function(vm) { vm.w = 100; vm.h = 100; vm.click = function() { vm.w = parseFloat(vm.w) + 10; vm.h = parseFloat(vm.h) + 10; } }) avalon.scan(document.getElementById('box')
就是官网提供的一个DEMO http://rubylouvre.github.io/mvvm/、
分析HTML结构:
JS处理中:
view model视图模型的构建在之前已经讲过了,这里主要讲下双向绑定的构建及处理的原理
1.构建VM的时候,对监控属性进程转化处理,生成一个监控对象
监控对象是经过Object.defineProperty转换过的处理函数,因此在setter,getter时候会调用转化的处理函数,这个用户是不可见的
赋值时处理 setter
var old = value; if (valueType === "array" || valueType === "object") { //监控数组 if (value && value.$id) { updateViewModel(value, neo, Array.isArray(neo)) } else if (Array.isArray(neo)) { value = Collection(neo) value._add(neo) } else { value = modelFactory(neo, neo) } } else { value = neo } accessor.value = value; model[name] = value && value.$id ? value.$model : value; //值变化了,通知顶层改变 notifySubscribers(accessor); vmodel.$fire && vmodel.$fire(name, value, old)
取值时处理 getter
collectSubscribers(accessor); //收集视图函数 return value
操做时
vm.w = 100 setter,就会默认调用赋值处理函数
vm.w 一样,getter 调用取值函数
这样方式,比ko的this.firstName() + " " + this.lastName(); 友爱多了,由于KO转换的是处理函数,必需要函数调用。。。别提多变扭
关键点:
collectSubscribers //收集视图函数
notifySubscribers //值变化了,通知顶层改变
这个2个方法,用来处理依赖关系的
实现的流程:
预处理过程:
交互时:
画了张图。。
本文只是很简单的说了下监控属性大概的逻辑,还有计算属性的处理,转化,调用,以后会分解
评价:实现很是巧妙,并且代码写的清晰易懂