迷你MVVM框架 avalonjs 0.85发布
迷你MVVM框架 avalonjs 0.85发布
本版本对循环绑定做了巨大改进,感谢@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.splicearray.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 = truecase "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) breakcase "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然后发布正式版。
迷你MVVM框架在github的仓库https://github.com/RubyLouvre/avalon
官网地址http://rubylouvre.github.io/mvvm/
大家可以加入QQ群:79641290进行讨论,此群为技术群,禁水!
迷你MVVM框架 avalonjs 0.85发布的更多相关文章
- 迷你MVVM框架 avalonjs 0.95发布
迷你MVVM框架 avalonjs 0.95发布 本版本最主要的改进是ms-with 深层绑定的实现,至少,avalon1.0所有重要的feature已经开发完毕,之后就是小补小漏,性能优化了. ms ...
- 迷你MVVM框架 avalonjs 0.82发布
迷你MVVM框架 avalonjs 0.82发布 本版本最大的改进是启用全新的parser. parser是用于干什么的?在视图中,我们通过绑定属性实现双向绑定,比如ms-text="fir ...
- 迷你MVVM框架 avalonjs 0.8发布
本版本最重要的特性是引进了AMD规范的模块加载器,亦即原来mass Framework 的并行加载器, 不同之处,它引进了requirejs的xxx!风格的插件机制,比如要延迟到DOM树建完时触发,是 ...
- 迷你MVVM框架 avalonjs 0.99发布
在本版本主要是性能优化,添加一些有用的功能(如回调什么的),离成品阶段不远了. 修正 updateViewModel bug 修正监控数组的set方法 bug 添加data-each-rendered ...
- 迷你MVVM框架 avalonjs 0.9发布
本版本最大的改进是引进了ms-with绑定,现在可轻松遍历对象了. 改进列表如下: 重新使用082的scanNodes方法,因为有关旧式IE下UI渲染锁死的问题已经解决了. 优化each绑定与Coll ...
- 迷你MVVM框架 avalonjs 0.91发布
本版本修了一些BUG与不合理的地方,感谢感谢ztz, 民工精髓, 姚立, qiangtou等人指正. 处理AMD加载 旧式IE下移除script节点内存泄漏的问题 fix firefox 全系列vis ...
- 迷你MVVM框架 avalonjs 0.92发布
本版本最大的改进是引入ms-class的新风格支持,以前的不支持大写类名及多个类名同时操作,新风格支持了.还有对2维监控数组的支持.并着手修复UI框架. 重构 class, hover, active ...
- 迷你MVVM框架 avalonjs 0.93发布
这段时间吸取@limodou, @东灵等人的意见,做了以下改进 重构isArrayLike,提高avalon.each的性能,原来avalon.each是依赖于isArrayLike来判定是循环普通对 ...
- 迷你MVVM框架 avalonjs 0.94发布
本版本主要做了如下改进: 优化ms-if的逻辑,现在描述DOM的顺序是 ms-skip, ms-important, ms-controller, ms-if ... 只要元素存在ms-skip 这个 ...
随机推荐
- 工作笔记3.手把手教你搭建SSH(struts2+hibernate+spring)环境
上文中我们介绍<工作笔记2.软件开发经常使用工具> 从今天開始本文将教大家怎样进行开发?本文以搭建SSH(struts2+hibernate+spring)框架为例,共分为3步: 1)3个 ...
- JS常用的标准函数
原文:JS常用的标准函数 1.Array类型函数 array.concat(item...) 函数功能:关联数组,实现数组相加功能,但并不影响原先数组,concat返回新数组. array.join( ...
- String 的intern() 方法说明
1.说明 Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回. 2.源码说明 public native ...
- [置顶] Vector ArrayList区别剖析
Java中Vector与ArrayList的区别?这是一个很常见的面试题目:) Vector与ArrayList其实是非常相似的,不信,你可以看看源码,如果说真的有什么区别的话,大概有以下三点: 1: ...
- script —— 终端里的记录器
当 你在终端或者控制台工作时,你可能想要记录在终端中所做的一切.这些记录可以用来当作史料,保存终端所发生的一切.比如说,你和一些Linux管理员们同 时管理着相同的机器,或者你让某人远程登陆到了你的服 ...
- UVA 10391 Compound Words
Problem E: Compound Words You are to find all the two-word compound words in a dictionary. A two-wor ...
- c内存结构
每个进程都运行在自己私有的内存空间中(即虚拟地址空间).在32位系统中,4GB的进程地址东健被分为用户空间和内核空间两个部分.用户空间占据着 0~3GB(用16进制表示为0xC0000000),而内核 ...
- The initialization of the CRM authentication pipline execution has failed
由于公司电路切换,昨天晚上不得不将服务器暂时关闭.早上重新开机时,发现开发环境连不上了.这可把我急坏了,大家可都等着开发呢. 于是查看服务器错误消息,发现时数据库连接连接不上. The initial ...
- Oracle 高级查询、事物、过程及函数
一.Sql函数 1.数值函数(输入参数和返回值都是数值型,多数函数精确到38位) --多少次方 ,) from dual; --开方 ) from dual; --绝对值 ) from dual; - ...
- Orchard网上商店模块
从头开始编写一个Orchard网上商店模块(1) - 介绍 原文地址:http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-w ...