博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
迷你MVVM框架 avalonjs 0.85发布
阅读量:6942 次
发布时间:2019-06-27

本文共 4331 字,大约阅读时间需要 14 分钟。

本版本对循环绑定做了巨大改进,感谢@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树。

我们看下面的注解:

{

{$index}}----{
{el}}

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与它进行扫描  此时它的内容应为

0 --- 1

将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然后发布正式版。

迷你MVVM框架在github的仓库

官网地址

大家可以加入QQ群:79641290进行讨论,此群为技术群,禁水!

转载地址:http://ugnnl.baihongyu.com/

你可能感兴趣的文章
[kmp+dp] hdu 4628 Pieces
查看>>
反射简介—类型反射和晚期绑定
查看>>
Lintcode: Binary Tree Serialization (Serialization and Deserialization Of Binary Tree)
查看>>
[设计模式] 9 装饰者模式 Decorator
查看>>
beetle.express针对websocket的高性能处理
查看>>
bat批处理设置Java JDK系统环境变量文件
查看>>
Javascript的setTimeOut()和setInterval()的定时器用法
查看>>
HDU 4819 Mosaic D区段树
查看>>
商务部
查看>>
ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步
查看>>
python静态方法和类方法
查看>>
iOS实现地图半翻页效果--老代码备用参考
查看>>
走过电竞之路的程序员
查看>>
JQ 获取地址栏参数
查看>>
关于AFNetworking访问网络超时的设置
查看>>
让前端独立于后端进行开发,模拟数据生成器Mock.js
查看>>
微信公众平台开发—利用OAuth2.0获取微信用户基本信息
查看>>
golang遇到的win下读取txt字符乱码的问题
查看>>
Binary Search--二分查找
查看>>
《计算机图形学》2.1.6 三维观察设备 学习笔记
查看>>