iuap design 源码分析系列-双MVVM模型
bluemind7788 opened this issue · comments
分析1 何谓双MVVM
现在已经有很多流行的MVVM框架,如knockout、vue、angular、avalon等,它们都实现了普通的html元素与简单数据(包括基本数据类型和数组)的双向绑定。但是在View层,除了普通的html元素,还有很多js插件,它们是在js代码中通过拼接html的方式渲染出来的前端展示,如很多的jquery插件;在Model层,简单的数据在一些场景下会有些力不从心,如knockout的数组,改变数组的一行中某列的值,View层并不能更新;列的元信息如字段名、校验规则等并不能在数组结构中表示;数组数据的选中行等统计信息,只能在数组外添加计算属性实现。
双MVVM除了实现普通html元素与简单数据绑定外,还实现了普通html元素与复杂数据、jsView插件与简单数据、jsView插件与复杂数据的绑定。
分析2 双MVVM的实现原理
普通html与简单数据、复杂数据的绑定通过knockout就可以搞定,这是我们的第一种绑定方式。
jsView插件与简单数据、复杂数据的绑定是需要针对每一个jsView插件加入一个中介者,这个中介者实现了数据的监听和控件的监听,当数据发生变化时,中介者会去调用jsView插件提供的api去更新view,当控件发生变化时,会调用复杂数据的api更新数据,这是我们的第二种绑定的实现的基本原理。
两种绑定方式的区别绑定view的粒度不同,一个是html元素级别,一个控件级别。在iuap design中,主要是实现了第二种绑定方式。
分析3 举例说明第二种绑定方式
这种绑定方式的代码在src/model/comp-adp目录下,我们以checkbox.js来分析。先看看简化版的代码
u.CheckboxAdapter = u.BaseAdapter.extend({
init: function (options) {
var self = this;
// 初始化控件
this.comp = new u.Checkbox(this.element);
this.element['u.Checkbox'] = this.comp;
// 监听控件的变化
this.comp.on('change', function(){
var modelValue = self.dataModel.getValue(self.field);
modelValue = modelValue ? modelValue : '';
if (self.comp._inputElement.checked) {
self.dataModel.setValue(self.field, self.checkedValue);
}else{
self.dataModel.setValue(self.field, self.unCheckedValue)
}
});
if(this.dataModel){
// 监听datatable的变化
this.dataModel.ref(this.field).subscribe(function(value) {
self.modelValueChange(value)
})
}
},
modelValueChange: function (val) {
var self = this;
if (this.comp._inputElement.checked != (val === this.checkedValue)){
this.comp.toggle();
}
}
})
可以看到通过new u.Checkbox(this.element)
进行了控件的初始化;this.comp.on('change', function(){...})
实现了控件的监听,监听的回调方法中通过self.dataModel.setValue(self.field, self.checkedValue)
进行了复杂数据datatable的改变;
this.dataModel.ref(this.field).subscribe(function(value) {
self.modelValueChange(value)
})实现了复杂数据的监听,在监听函数
modelValueChange中通过
this.comp.toggle()`对控件进行了更新。