本版本对循环绑定做了巨大改进,感谢@soom, @limodou, @ztz, @Gaubee 提供的大量测试文件。
- fix scanNodes, 在循环绑定(ms-each)扫描元素节点时必须 nextTick,否则旧式IE会忙碌不过来。
- fix ms-css ,旧式IE style[name] = value, 当value为NaN ,不带单位或不是数值什么会抛异常,需要try catch。
- 旧式IE下有些元素的innerHTML是只读的, 因此不能一律使用innerHTML,并且有些元素的生成,如script标签是不会执行,为此我引入新的parseHTML模块来处理此事。
- fix AMD 加载因为手误进错分支的BUG
- fix scanExpr bug, 它在IE10有时会多生成一个绑定对象,异致不渲染错误。
- 重构Collection内部对象与ms-each绑定,引入“事务”的概念,让其插入节点时更加智能高效。
我们看最后一条,我们可以类似纯JS操作为内存操作,DOM操作为IO操作,执行一万次前者所需的时间可能还比不上一次后者的。DOM操作的开销就是这么大。有的DOM操作还会引起reflow,这危害更大。因此明智的做法就是将要操作的节点移出DOM树。更好的办法是,此多个DOM操作合成一个,全部在文档碎片中搞完才插入DOM树。
我们看下面的注解:
< div ms-controller = "box" >
< div ms-each-el = "array" id = "aaa" >
< p >{{$index}}----{{el}}</ p >
</ div >
</ div >
avalon.define("box", function(vm) { vm.array = [1, 2, 3, 4, 5]
}) 实现过程 当扫描到div#aaa 将div#aaa的所有子节点复制一份到文档碎片vTemplate 执行begin命令,将vTemplate复制一个空的文档碎片vTransation( cloneNode(false) ), 设置全局变量flagTransation = true; 开始循环数组
执行insert命令
将vTemplate复制一个文档碎片vEl( cloneNode(true) ),
将对应的子VM与它进行扫描 此时它的内容应为 < p >0 --- 1</ p >
将vEl appendChild到 vTemplate
.....
重复执行array.length次
执行commit命令,将vTemplate append到div#aaa节点中, 设置全局变量flagTransation = false 重新排列所有$index |
在数组有关添加元素的push, unshift, splice这三个方法中,都调用了add方法,它里面就默认使用事件进行处理。
array._splice = array.splice array.add = function (arr, insertPos) {
insertPos = typeof insertPos === "number" ? insertPos : this .length;
notifySubscribers( this , "begin" )
for ( var i = 0, n = arr.length; i < n; i++) {
var el = convert(arr[i])
var pos = insertPos + i
this ._splice(pos, 0, el)
notifySubscribers( this , "insert" , pos, el)
}
notifySubscribers( this , "commit" , insertPos)
if (! this .stopFireLength) {
return dynamic.length = this .length
}
} |
notifySubscribers会向上通知updateListView方法,然后让它执行相关的DOM操作
case "begin" :
list.vTransation = data.vTemplate.cloneNode( false )
flagTransation = true
case "insert" :
//将子视图插入到文档碎片中
var tmodel = createVModel(pos, el, list, data.args)
var tview = data.vTemplate.cloneNode( true )
tmodel.$view = tview
vmodels = [tmodel].concat(vmodels)
tmodels.splice(pos, 0, tmodel)
scanNodes(tview, vmodels);
data.group = ~~tview.childNodes.length //记录每个模板一共有多少子节点
list.vTransation.appendChild(tview)
break
case "commit" :
pos = ~~pos
//得到插入位置 IE6-10要求insertBefore的第2个参数为节点或null,不能为undefined
var insertNode = parent.childNodes[ data.group * pos] || null
parent.insertBefore(list.vTransation, insertNode)
flagTransation = false
resetItemIndex(tmodels)
break
|
嘛,不过这次改动太大了,有关Collection与bindingHandlers["each"]的代码都几乎改清光。另一个值得一提的是VM数组在腓序时,与视图的同步。这里涉及如何让一个数组基于另一个数组进行排序,我的解决方式如下:
var aaa = [1, 2, 3, 4, 5, 1]
var bbb = [{v: 2}, {v: 3}, {v: 1}, {v: 1}, {v: 5}, {v: 4}]
var swapTime = 0
var isEqual = Object.is || function (x, y) { //主要用于处理NaN 与 NaN 比较
if (x === y) {
return x !== 0 || 1 / x === 1 / y;
}
return x !== x && y !== y;
};
for ( var i = 0, n = bbb.length; i < n; i++) {
var a = aaa[i];
var b = bbb[i]
var b = b && b.v ? b.v : b
if (!isEqual(a, b)) {
console.log(++swapTime)
var index = getIndex(a, bbb, i);
var el = bbb.splice(index, 1)
bbb.splice(i, 0, el[0])
}
}
function getIndex(a, bbb, start) {
for ( var i = start, n = bbb.length; i < n; i++) {
var b = bbb[i];
var check = b && b.v ? b.v : b
if (isEqual(a, check)) {
return i
}
}
}
console.log(JSON.stringify(bbb))
//在框架中,aaa为数据模型M中的数组,bbb为视图模型VM中的数组 |
如果有更好的算法,请多多指教。
经过这次大重构后,avalon在API上基本没有变化了,未来的v0.9就是fix BUG然后发布正式版。
相关推荐
一个迷你框架
Android mvvm 框架,最流行的mvvm demo 无bug
Vue.js是一套构建用户界面的轻量级MVVM框架,与其他重量级框架不同的是, Vue.js 的核心库只关注视图层,并且非常容易学习,很容易与其它前端技术或已有的项目整合。 本系课程,主要分为两部分完成。第一部分:掌握...
WPF MVVM框架的简单学习 WPF MVVM框架的简单学习 WPF MVVM框架的简单学习
MVVM框架的demo,
首先从http://mvvmlight.codeplex.com/或者http://files.cnblogs.com/chengxingliang/GalaSoft.MvvmLight.V3.rar下载它的MVVM框架下来,安装上之后,...该程序是我学习MVVM框架学习制作的小示例,很适合mvvm框架入门。
史上最强 MVVM 框架 艺术帮是一款艺术图片应用,采用LiveData+ViewModel+RxJava+okHttp+Retrofit+Glide架构的项目,仅用于学习交流
WPF MVVM 框架WPF MVVM 框架WPF MVVM 框架WPF MVVM 框架WPF MVVM 框架
一步一个脚印实现一个自己的简易MVVM框架
mvvm框架整合demo 在demo内有其他的实例,和其他实用框架有利于初学都学习,也有很多的代码注释
互联网的不断发展,前端开发人员一直致力于开发更加高效的代码,由于前期网速以及前端语言的限制,始终得不到解决,近年来,这些问题...该文就近年来出现的MVVM框架中的Vue做出一些深入的研究,解析MVVM框架的原理及实现。
vs2010开发WPF采用MVVM框架一个简单的实例,初学者可以参考一下。
WPF MVVM框架简单实例代码,适合初学者
WPF编写的MVVM框架,可以拿来直接修改成自己的项目(框架比较基础,但大部分功能已经可以实现)
适用于初学者的MVVM框架,带导航,页面跳转等。 Dialog Popup WPF C#
WPF mvvm框架Stylet使用教程-窗体交互用法,打开窗体、关闭窗体
一个简单的MVVM框架
Prismv4 MVVM框架安装文件 Prismv4 MVVM框架安装文件 Prismv4 MVVM框架安装文件
大家都知道,vue是个MVVM框架,能够实现view和model的双向绑定,不像backbone那样,model改变需要手动去通知view更新,而vue实现的原理就是通过Object.defineProperty实现数据挟持,定义setter,然后数据改变的时候...
本文的框架主要是简单,可以快速解耦 ViewModel 和 View 依赖,解耦 ViewModel 之间依赖,减少 ViewModel 的代码量