迷你MVVM框架 avalonjs 沉思录 第3节 动态模板

模板的发明是编程史上的一大里程碑,让我们摆脱了烦锁且易出错的字符串拼接,维护性大大提高。

都在JSP,ASP时代,人们已经学会使用include等语句,将多个页面片断拼接成一个页面。
此外,为了将数据库中的数据或业务中用到的变量输出到页面,我们需要将页面某个地方标记一下,将变量塞到里面去。
最后,出于方便循环输出一组数据,就需要将each语句从HTML里撕开一道口子,加上其他什么if语句,页面上其实变撕裂成两部分
一种是与后端语言相近的逻辑部分,一个是够为纯净的HTML部分,到最后,模板引擎就发展出来。

在jQuery王朝的后期,业务逻辑不断往前搬,前端模板也发明出来了。这些模板我统称为静态模板或字符串模板,特征是模板是放在
一个script标签或textarea标签里。静态模板的好处是统一管理,我们从script标签等抽取内容时,它是原汁原味,没有变量。
缺点是破坏原有的结构。MVVM时代,knockout,
ember等率先发明动态模板,或叫DOM模块,特点是通过在元素节点上标记一些特殊属性,注明此元素里面会输出什么内容
或此元素的子元素是作用循环体要循环多少次,当然if等输出不输出很小儿科。缺点是,需要对文档的整体或某一区域进行扫描,这里耗时比静态模板多上几倍,并且定界符(用于输出变量的标记)可能离奇失踪。但这也没什么大不了,现在流行的两种定界符形式≈lt&;,
%>
{{ }}在IE10+或W3C浏览器活得好好的,IE6-9,我们只要避开大于小于号就行了。
此外动态模板与静态模板最大的不同在于,它是没有编译函数,而是通过扫描文档,根据节点上的定界符与绑定属性实现循环输出,填空等功能。

我们看一下avalon是怎么做的。大致分两块,定义VM,添加绑定。VM是我们操作的主体,绑定是将页面变成模板的关键。

VM的定义

avalon.define("test",function(vm){
vm.aaa = "司徒正美"
})

avalon.define是用来定义VM,第一个参数为VM的ID名,这是用于在页面圈定作用域的范围,对应的绑定属性是ms-controller。因为一个页面可能有多人负责,就存在多个VM了,而VM相当于一个数据据,它们都用于不同的区域,这里就需要用ID来区分了。

添加绑定,我们随便往body一塞就行了

<body>{{aaa}}</body>

这里的{{ }}是定界符,放在文本节点里。我们可以用过avalon.config({interpolate: ["{?",
"?}"]})来设置定界符。

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"> </script>
<script>
avalon.define("test", function(vm){
vm.aaa = "司徒正美"
})
</script>
</head>
<body ms-controller="test">
<h3>{{aaa}}</h3>
{{aaa}}
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"> </script>

<script>
avalon.define("test", function(vm){
vm.aaa = "司徒正美"
})
</script>
</head>
<body ms-controller="test">
<h3>{{aaa}}</h3>
{{aaa}}
</body>
</html>

运行代码

但世界上没有这么简单的页面,比如我们要输出一个列表,是不是要这样干呢?

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.a = "2014预言:阿里死磕港交所"
vm.b = "马云进军游戏背后:恐失势电商"
vm.c = "支付宝信息泄露揭大公司管理困境"
vm.d = "盘点2013:智能手机开启的新场景"
})
</script>
</head>
<body ms-controller="test">
<ol>
<li>{{a}}</li>
<li>{{b}}</li>
<li>{{c}}</li>
<li>{{d}}</li>
</ol>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.a = "2014预言:阿里死磕港交所"
vm.b = "马云进军游戏背后:恐失势电商"
vm.c = "支付宝信息泄露揭大公司管理困境"
vm.d = "盘点2013:智能手机开启的新场景"
})
</script>
</head>
<body ms-controller="test">
<ol>
<li>{{a}}</li>
<li>{{b}}</li>
<li>{{c}}</li>
<li>{{d}}</li>
</ol>
</body>
</html>

运行代码

当然不行,这要定义多少个变量啊!这时就需用到循环绑定,ms-repeat!

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.array = ["2014预言:阿里死磕港交所",
"马云进军游戏背后:恐失势电商",
"支付宝信息泄露揭大公司管理困境", "盘点2013:智能手机开启的新场景"]
})
</script>
</head>
<body ms-controller="test">
<ol>
<li ms-repeat="array">{{el}}</li>
</ol>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.array = ["2014预言:阿里死磕港交所",
"马云进军游戏背后:恐失势电商",
"支付宝信息泄露揭大公司管理困境", "盘点2013:智能手机开启的新场景"]
})
</script>
</head>
<body ms-controller="test">
<ol>
<li ms-repeat="array">{{el}}</li>
</ol>
</body>
</html>

运行代码

ms-repeat相当于ms-each-el,后面的-el是可配置可省略。比如改成ms-repeat-elem,那么对应的位置要改成{{elem}}。

我们还可以输出2维数组

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.array = [[1, 2], [4, 5], [7, 8]]
})
</script>
</head>
<body ms-controller="test">
<table width="80%" border="1">
<tr ms-repeat-item="array">
<td ms-repeat="item">{{el}}</td>
</tr>
</table>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.array = [[1, 2], [4, 5], [7, 8]]
})
</script>
</head>
<body ms-controller="test">
<table width="80%" border="1">
<tr ms-repeat-item="array">
<td ms-repeat="item">{{el}}</td>
</tr>
</table>
</body>
</html>

运行代码

输出对象数组

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.array = [{name: 111}, {name: 222}, {name: 333}]
})
</script>

</head>
<body ms-controller="test">
<ul>
<li ms-repeat-me="array">{{me.name}}</li>
</ul>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.array = [{name: 111}, {name: 222}, {name: 333}]
})
</script>

</head>
<body ms-controller="test">
<ul>
<li ms-repeat-me="array">{{me.name}}</li>
</ul>
</body>
</html>

运行代码

现在大家算是对ms-repeat算是有一个大体的了解吧。那么我们学一点高级的。avalon.define会返回一个VM对象,我们通过操作它就能实现页面的操作数据即操作DOM!!!,比如vmodel.array.push。另,我们想输出每个元素对应的索引值,可以使用$index这个变量。

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.array = [{name: 111}, {name: 222}, {name: 333}]
})
var array = model.array
setInterval(function(){
array.push({name: Math.random().toString(32).substr(4,14)})
if(array.length > 10){
array.shift()
}
},500)
</script>

</head>
<body ms-controller="test">
<ul>
<li ms-repeat="array">{{$index}}--{{el.name}}</li>
</ul>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.array = [{name: 111}, {name: 222}, {name: 333}]
})
var array = model.array
setInterval(function(){
array.push({name: Math.random().toString(32).substr(4,14)})
if(array.length > 10){
array.shift()
}
},500)
</script>

</head>
<body ms-controller="test">
<ul>
<li ms-repeat="array">{{$index}}--{{el.name}}</li>
</ul>
</body>
</html>

运行代码

之所以 能有这样神奇的效果,是因为avalon会将VM中的数组转换为监控数组,它拥有以下方法:

push, shift, unshift, pop, slice, splice, remove, removeAt,
removeAll, clear, ensure, sort, reverse, set

现在我们跳前一步,学一下ms-on-*绑定,实现一个更复杂的效果。ms-on-*的*对应一个事件名,属性值为VM中一个函数名,与元素onkeypress,
onclick一样,它的第一个参数默认是事件对象,this指向元素节点,不同的是我们已经对IE6-8下的事件对象做了兼容处理。

<!DOCTYPE HTML>
<html>
<head>
<title>ms-repeat</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.array = ["1", "2", "3", "4"]
"push,unshift,remove,ensure".replace(/\w+/g, function(method) {
vm[method] = function(e) {
if (this.value && e.which == 13) {//this为input元素
vm.array[method](this.value);
this.value = "";
}
}
})

vm.removeAt = function(e) {
if (isFinite(this.value) && e.which == 13) {//this为input元素
var a = ~~this.value
vm.array.removeAt(a)
this.value = "";
}
}
"pop,shift,sort,reverse".replace(/\w+/g, function(method) {
vm[method] = function(e) {
vm.array[method]();
}
})
});

</script>
</head>
<body ms-controller="test">
<p>监控数组拥有以下方法,我们可以操作它们就能同步对应的区域</p>
<blockquote>
push, shift, unshift, pop, slice, splice, remove, removeAt, removeAll, clear, ensure, sort, reverse, set
</blockquote>
<ul>
<li ms-repeat="array">数组的第{{$index+1}}个元素为{{el}}</li>
</ul>
<p>对数组进行push操作,并回车<input ms-on-keypress="push"></p>
<p>对数组进行unshift操作,并回车<input ms-on-keypress="unshift"></p>
<p>对数组进行ensure操作,并回车<input ms-on-keypress="ensure"><br/>
(只有数组不存在此元素才push进去)</p>
<p>对数组进行remove操作,并回车<input ms-on-keypress="remove"></p>
<p>对数组进行removeAt操作,并回车<input ms-on-keypress="removeAt"></p>
<p><button type="button" ms-on-click="sort">对数组进行sort操作</button></p>
<p><button type="button" ms-on-click="reverse">对数组进行reverse操作</button></p>
<p><button type="button" ms-on-click="shift">对数组进行shift操作</button></p>
<p><button type="button" ms-on-click="pop">对数组进行pop操作</button></p>
<p>当前数组的长度为<span style="color:red">{{array.size()}}</span>,注意 我们无法修改数组length的固有行为,因此它无法同步视图,需要用size方法。</p>
</body>
</html>


<!DOCTYPE HTML>
<html>
<head>
<title>ms-repeat</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
avalon.define("test", function(vm) {
vm.array = ["1", "2", "3", "4"]
"push,unshift,remove,ensure".replace(/\w+/g, function(method) {
vm[method] = function(e) {
if (this.value && e.which == 13) {//this为input元素
vm.array[method](this.value);
this.value = "";
}
}
})

vm.removeAt = function(e) {
if (isFinite(this.value) && e.which == 13) {//this为input元素
var a = ~~this.value
vm.array.removeAt(a)
this.value = "";
}
}
"pop,shift,sort,reverse".replace(/\w+/g, function(method) {
vm[method] = function(e) {
vm.array[method]();
}
})
});

</script>
</head>
<body ms-controller="test">
<p>监控数组拥有以下方法,我们可以操作它们就能同步对应的区域</p>
<blockquote>
push, shift, unshift, pop, slice, splice, remove, removeAt, removeAll, clear, ensure, sort, reverse, set
</blockquote>
<ul>
<li ms-repeat="array">数组的第{{$index+1}}个元素为{{el}}</li>
</ul>
<p>对数组进行push操作,并回车<input ms-on-keypress="push"></p>
<p>对数组进行unshift操作,并回车<input ms-on-keypress="unshift"></p>
<p>对数组进行ensure操作,并回车<input ms-on-keypress="ensure"><br/>
(只有数组不存在此元素才push进去)</p>
<p>对数组进行remove操作,并回车<input ms-on-keypress="remove"></p>
<p>对数组进行removeAt操作,并回车<input ms-on-keypress="removeAt"></p>
<p><button type="button" ms-on-click="sort">对数组进行sort操作</button></p>
<p><button type="button" ms-on-click="reverse">对数组进行reverse操作</button></p>
<p><button type="button" ms-on-click="shift">对数组进行shift操作</button></p>
<p><button type="button" ms-on-click="pop">对数组进行pop操作</button></p>
<p>当前数组的长度为<span style="color:red">{{array.size()}}</span>,注意 我们无法修改数组length的固有行为,因此它无法同步视图,需要用size方法。</p>
</body>
</html>

运行代码

有了批量输出的ms-repeat及通过调用监控数组的方法就能实现对应节点的删除添加排序,那么实现grid简直易如反掌。

<!DOCTYPE HTML>
<html>
<head>
<title>ms-repeat</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
if (!Date.now) {
Date.now = function() {
return new Date - 0;
}
}
avalon.define(‘test‘, function(scope) {
scope.selected = "name"
scope.options = ["name", "size", "date"]
scope.trend = 1
scope.data = [
{name: "aaa", size: 213, date: Date.now() + 20},
{name: "bbb", size: 4576, date: new Date - 4},
{name: "ccc", size: 563, date: new Date - 7},
{name: "eee", size: 3713, date: 9 + Date.now()},
{name: "555", size: 389, date: Date.now() - 20}
];
scope.$watch("selected", function(v) {
var t = parseFloat(scope.trend)
scope.data.sort(function(a, b) {
var ret = a[v] > b[v] ? 1 : -1
return t * ret
})
})
scope.$watch("trend", function(t) {
var v = scope.selected, t = parseFloat(t)
scope.data.sort(function(a, b) {
var ret = a[v] > b[v] ? 1 : -1
return t * ret
})
})
});

</script>
</head>
<body ms-controller="test">
<p>
<select ms-duplex="selected">
<option ms-repeat="options">{{el}}</option>
</select>
<select ms-duplex="trend">
<option value="1">up</option>
<option value="-1">down</option>
</select>
</p>
<table width="500px" border="1">
<tbody >
<tr ms-repeat="data">
<td>{{el.name}}</td> <td>{{el.size}}</td> <td>{{el.date}}</td>
</tr>
</tbody>
</table>
</body>
</html>


<!DOCTYPE HTML>
<html>
<head>
<title>ms-repeat</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
if (!Date.now) {
Date.now = function() {
return new Date - 0;
}
}
avalon.define(‘test‘, function(scope) {
scope.selected = "name"
scope.options = ["name", "size", "date"]
scope.trend = 1
scope.data = [
{name: "aaa", size: 213, date: Date.now() + 20},
{name: "bbb", size: 4576, date: new Date - 4},
{name: "ccc", size: 563, date: new Date - 7},
{name: "eee", size: 3713, date: 9 + Date.now()},
{name: "555", size: 389, date: Date.now() - 20}
];
scope.$watch("selected", function(v) {
var t = parseFloat(scope.trend)
scope.data.sort(function(a, b) {
var ret = a[v] > b[v] ? 1 : -1
return t * ret
})
})
scope.$watch("trend", function(t) {
var v = scope.selected, t = parseFloat(t)
scope.data.sort(function(a, b) {
var ret = a[v] > b[v] ? 1 : -1
return t * ret
})
})
});

</script>
</head>
<body ms-controller="test">
<p>
<select ms-duplex="selected">
<option ms-repeat="options">{{el}}</option>
</select>
<select ms-duplex="trend">
<option value="1">up</option>
<option value="-1">down</option>
</select>
</p>
<table width="500px" border="1">
<tbody >
<tr ms-repeat="data">
<td>{{el.name}}</td> <td>{{el.size}}</td> <td>{{el.date}}</td>
</tr>
</tbody>
</table>
</body>
</html>

运行代码

这里用到了ms-duplex, $watch,大家可以到《入门教程》看看,都是很简单的东西。

接着我们再看看如何循环输出对象吧,它也是用ms-repeat,不过里面的变量为$key, $val。不用多言,看例子。

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.object = {
grape: "葡萄",
coconut: "椰子",
pitaya: "火龙果",
orange: "橙子"
}

})

</script>

</head>
<body ms-controller="test">
<ul>
<li ms-repeat="object">{{$key}}--{{$val}}</li>
</ul>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.object = {
grape: "葡萄",
coconut: "椰子",
pitaya: "火龙果",
orange: "橙子"
}

})

</script>

</head>
<body ms-controller="test">
<ul>
<li ms-repeat="object">{{$key}}--{{$val}}</li>
</ul>
</body>
</html>

运行代码

好了,循环输出就到这里。我们最后看一下如何实现其他模板引擎的if语句。它的名字为ms-if,如果值为真就输出,否则不输出。

<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.toggle = true
vm.click = function(){
vm.toggle = !vm.toggle
}
vm.text = "捉迷藏"

})

</script>

</head>
<body ms-controller="test">
<p ms-if="toggle">{{text}} </p>
<button type="button" ms-on-click="click">点我{{toggle ? ‘隐藏‘ : "显示"}}</button>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>avalon</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="http://files.cnblogs.com/rubylouvre/avalon20130929.js"></script>
<script>
var model = avalon.define("test", function(vm) {
vm.toggle = true
vm.click = function(){
vm.toggle = !vm.toggle
}
vm.text = "捉迷藏"

})

</script>
</head>
<body ms-controller="test">
<p ms-if="toggle">{{text}} </p>
<button type="button" ms-on-click="click">点我{{toggle ? ‘隐藏‘ : "显示"}}</button>
</body>
</html>

运行代码

{{}}, ms-repeat,
ms-if
这就是动态模板相对静态模板的所有功能了,但由于动态模板在扫描之后,得到所有要处理的节点的引用,这也意味着,以后我们要做一小部分的更新,不用像静态模板那样大规模替换,而是细化到每一个元素节点,特性节点或文本节点。这就是所谓的“最小化刷新”技术。一般的,只有ms-if等少量绑定才影响到元素节点那一层面,更多的时候,
我们是在刷新特性节点的value值,文本节点的data值,这也意味着,我们的刷新不会引起reflow。加之,能得到元素节点本上,我们就可以轻松实现绑定事件,操作样式,修改属性等功能。这也是为什么大多数MVVM框架选择动态模板的缘故,jQuery原来可以做的,我们全部通过绑定属性或定界符在HTML里搞定。
这也意味着,我们实现了完美的分层架构,JS里面是纯粹的模型层(包括model与viewmodel),HTML里是学习成本与维护成本极低的视图层。这已经不是多了一个模板引擎这么简单的事,我们抢到了
一直以来属性于后端的禁脔——分层架构

如果您觉得这文章对您有帮助,可以打赏点钱给我,鼓励我继续写一些高质量的博文


迷你MVVM框架 avalonjs 沉思录 第3节 动态模板,布布扣,bubuko.com

时间: 2024-08-02 10:50:49

迷你MVVM框架 avalonjs 沉思录 第3节 动态模板的相关文章

迷你MVVM框架 avalonjs 沉思录 第1节 土耳其开局

#cnblogs_post_body p{ text-indent:2em; margin-top: 1em; } 正如一切传说的开端那样,有一远古巨神开天辟地,然后就是其他半神喧宾夺主.我们对最巨贡献与创建力的远古巨神懵懂不知,却对巫师们的话语津津乐道.这同样也是我们前端的现实. MVVM是来自.NET,另一个遥远的界域.前端,相对于后端,怎么看都是蛮夷之地.JS这个肩负着前端一切交互工作的语言,竟然被视为恶魔,屡屡被屏蔽禁用.些微可用的脚本,变量与函数没有组织地野蛮生长着,直到JAVA的传教

迷你MVVM框架 avalonjs 沉思录 第2节 DOM操作的三大问题

jQuery之所以击败Prototype.js,是因为它自一开始就了解这三大问题,并提出完善的解决方案. 第一个问题,DOM什么时候可用.JS不像C那样有一个main函数,里面的逻辑不分主次.但JS是这样玩,并不意味着DOM也是这样.被JS自由惯了的人,于是傻眼了. 这涉及一个时间的概念.牛顿与爱因斯坦的差别,也是在于这个时间的引入.我们的脚本并不是一下子就引入,页面也不是一下加载完毕.前者引发脚本加载管理问题,后者就是DOMReady这个概念的导入.页面是从上到下生成,除了样式或图片在浏览器的

迷你MVVM框架 avalonjs 入门教程(司徒正美)

迷你MVVM框架 avalonjs 入门教程 关于AvalonJs 开始的例子 扫描 视图模型 数据模型 绑定属性与动态模板 作用域绑定(ms-controller, ms-important) 模板绑定(ms-include) 数据填充(ms-text, ms-html) 类名切换(ms-class, ms-hover, ms-active) 事件绑定(ms-on,……) 显示绑定(ms-visible) 插入绑定(ms-if) 双工绑定(ms-duplex) 样式绑定(ms-css) 数据绑

迷你MVVM框架 avalonjs 1.3.1发布

avalon1.3.1发布. interpolate支持注释节点做定界符,avalon.config({interpolate:["<!--","-->"]}) 监控数组添加pushArray方法,类似于push方法,不过参数是一个数组 data-duplex-changed回调会在第一次赋值就触发 添加一配置项,调整ms-repeat的对象池的大小,avalon.config({maxRepeatSize:30}) 迷你MVVM框架在github的仓库

迷你MVVM框架 avalonjs 1.3.2发布

时隔一个月,avalon的新版本终于出来了,本次更新带来强大的模块间通信机制,其他就往常一样FIX BUG. 在文本绑定里,IE会对流离于DOM树外的文本节点的data属性赋值报错,需要添加一层判定 派发事件的逻辑,由DOC.createEvent("Event")必成DOC.createEvent("Events") 添加一个反XSS的过滤器sanitize 重构事件系统,暴露eventHooks对象 firefox添加对mousewheel的兼容支持 升级ms-

迷你MVVM框架 avalonjs 1.3.3发布

这应该是1.3X系列最后一个版本了,大家可以在仓库中看到,多出了一个叫avalon.observe的东西,它是基于Object.observe,dataset, Promise等新API实现.其中,它也使用全新的静态收集依赖的机制,这个机制也完成得差不多,因此avalon与avalon.mobile下一版将会应用这最新成果,进行大改. fix IE6-8下直接修改表单元素值不触发data-duplex-changed回调的BUG, 详见这里 chrome浏览器对文本域进行Ctrl+V操作,会触发

迷你MVVM框架 avalonjs 1.3.5发布

本版本主要是修复内存泄漏问题,让其在移动端更好的运作. 修正visible BUG 详见这里 修正$fire方法里的正则错误 详见这里 修正ms-attr BUG,在IE9-11,直接用element.setAttribute("value","xxx")还是不能同步到element.value 详见这里 修正ms-class BUG,现在ms-hover对应的属性发生变成,类名也能跟着变了详见这里 修正avalon.modern的AMD加载器的onerror触发逻

迷你MVVM框架 avalonjs 1.3.8发布

avalon1.3.8主要是在ms-repeat. ms-each. ms-with等循环绑定上做重大性能优化,其次是对一些绑定了事件的指令添加了roolback,让其CG回收更顺畅. 重构ms-repeat.ms-each.ms-with, 内部的代理对象全部使用普通的对象实现, 并且一个监控数组只对应一个代理VM数组,从而大量减少VM的数量. avalon不再使用scanCallback实现内部各种rendred回调,改成checkScan方法.详看这里的例子. fix parseHTML在

迷你MVVM框架 avalonjs 1.3.7发布

又到每个月的15号了,现在avalon已经固定在每个月的15号发布新版本.这次发布又带来许多新特性,让大家写码更加轻松,借助于"操作数据即操作DOM"的核心理念与双向绑定机制,现在越来越多人加入到avalon的阵营中来.此外,基于avalon的UI库OniUI也越来越强大,很快,树组件也开发完毕,下星期也与大家见面了.到时,OniUI也有两个Grid组件,一个树组件的完整UI库.与本次发布的UI还有验证组件,mask组件,百叶窗切换组件-- UI库的广告就到时为止,我们看一下新版本带来