类名切换(ms-class, ms-hover, ms-active)avalon提供了多种方式来绑定类名,有ms-class, ms-hover, ms-active, 具体可看这里 事件绑定(ms-on)avalon通过ms-on-click或ms-click进行事件绑定,并在IE对事件对象进行修复,具体可看这里 avalon并没有像jQuery设计一个近九百行的事件系统,连事件回调的执行顺序都进行修复(IE6-8,attachEvent添加的回调在执行时并没有按先入先出的顺序执行),只是很薄的一层封装,因此性能很强。 - ms-click
- ms-dblclick
- ms-mouseout
- ms-mouseover
- ms-mousemove
- ms-mouseenter
- ms-mouseleave
- ms-mouseup
- ms-mousedown
- ms-keypress
- ms-keyup
- ms-keydown
- ms-focus
- ms-blur
- ms-change
- ms-scroll
- ms-animation
- ms-on-*
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>有关事件回调传参</title>
<script src="avalon.js" type="text/javascript"></script>
<script>
avalon.ready(function() {
avalon.define({
$id: "simple",
firstName: "司徒",
lastName: "正美",
array: ["aaa", "bbb", "ccc"],
argsClick: function(e, a, b) {
alert(a+ " "+b)
},
loopClick: function(a) {
alert(a)
}
});
avalon.scan();
})
</script>
</head>
<body>
<fieldset ms-controller="simple">
<legend>例子</legend>
<div ms-click="argsClick($event, 100, firstName)">点我</div>
<div ms-each-el="array" >
<p ms-click="loopClick(el)">{{el}}</p>
</div>
</fieldset>
</body>
</html>
|
另外,这里有一些结合ms-data实现事件代理的技巧,建议事件绑定接口支持事件代理,最简单就是table上可以绑定td的点击事件 显示绑定(ms-visible)avalon通过ms-visible="bool"实现对某个元素显示隐藏控制,它用是style.display="none"进行隐藏。
插入绑定(ms-if)这个功能是抄自knockout的,ms-if="bool",同样隐藏,但它是将元素移出DOM。这个功能直接影响到CSS :empty伪类的渲染结果,因此比较有用。 <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ms-if</title>
<script t src="avalon.js"></script>
</head>
<body ms-controller="test">
<ul ms-each-item="array">
<li ms-click="$remove" ms-if="$index % 2 == 0">{{ item }} --- {{$index}}</li>
</ul>
<script type="text/javascript">
avalon.define({
$id: "test",
array: "a,b,c,d,e,f,g".split(",")
});
</script>
</body>
</html>
|
这里得介绍一下avalon的扫描顺序,因为一个元素可能会存在多个属性。总的流程是这样的: ms-skip --> ms-important --> ms-controller --> ms-if --> ms-repeat --> ms-if-loop --> ...-->ms-each --> ms-with --> ms-duplex 首先跑在最前面的是 ms-skip,只要元素定义了这个属性,无论它的值是什么,它都不会扫描其他属性及它的子孙节点了。然后是 ms-important, ms-controller这两个用于圈定VM的作用域的绑定属性,它们的值为VM的$id,它们不会影响avalon继续扫描。接着是ms-if,由于一个页面可能被当成子模块,被不同的VM所作用,那么就会出现有的VM没有某个属性的情况。比如下面的情况: <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ms-if</title>
<script src="avalon.js"></script>
</head>
<body ms-controller="Test">
<h1>{{aaa}}</h1>
<ul ms-if="array" ms-each-item="array">
<li ms-click="$remove" ms-if="$index % 2 == 0">{{ item }} --- {{$index}}</li>
</ul>
<script type="text/javascript">
avalon.define('Test', function(vm) {
vm.aaa = "array不存在啊"
});
</script>
</body>
</html>
|
如果没有ms-if做代码防御,肯定报一大堆错。 接着是 ms-repeat绑定。出于某些原因,我们不想显示数组中的某些元素,就需要让ms-if拖延到它们之后才起作用,这时就要用到ms-if-loop。 <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ms-if</title>
<script src="avalon.js"></script>
</head>
<body ms-controller="test">
<h1>{{aaa}}</h1>
<ul>
<li ms-repeat="array" ms-if-loop="el">{{ el }}</li>
<li>它总在最后</li>
</ul>
<script type="text/javascript">
avalon.define({
$id: "test",
array: ["aaa", "bbb", null, "ccc"]
});
</script>
</body>
</html>
|
之后就是其他绑定,但殿后的总是ms-duplex。从ms-if-loop到ms-duplex之间的执行顺序是按这些绑定属性的首字母的小写的ASCII码进行排序,比如同时存在ms-attr与ms-visible绑定,那么先执行ms-attr绑定。如果我们想绑定多个类名,用到ms-class, ms-class-2, ms-class-3, ms-class-1,那么执行顺序为ms-class, ms-class-1, ms-class-2, ms-class-3。如果我们要用到绑定多个点击事件,需要这样绑定:ms-click, ms-click-1, ms-click-2……更具体可以查看源码中的scanTag, scanAttr方法。
双工绑定(ms-duplex)这功能抄自angular,原名ms-model起不得太好,姑且认为利用VM中的某些属性对表单元素进行双向绑定。 这个绑定,它除了负责将VM中对应的值放到表单元素的value中,还对元素偷偷绑定一些事件,用于监听用户的输入从而自动刷新VM。 对于select type=multiple与checkbox等表示一组的元素, 需要对应一个数组;其他表单元素则需要对应一个简单的数据类型;如果你就是想表示一个开关,那你们可以在radio, checkbox上使用ms-duplex-checked,需要对应一个布尔(在1.3.6之前的版本,radio则需要使用ms-duplex, checkbox使用ms-duplex-radio来对应一个布尔)。 | 新 | 旧(1.3.6之前) | 功能 | ms-duplex-checked 只能应用于radio、 checkbox | ms-duplex 只能应用于radio
ms-duplex-radio checkbox 多用于实现GRID中的全选/全不选功能 | 通过checked属性同步VM | ms-duplex-string 应用于所有表单元素 | ms-duplex-text 只能应用于radio | 通过value属性同步VM | ms-duplex-boolean 应用于所有表单元素 | ms-duplex-bool 只能应用于radio | value为”true”时转为true,其他值转为false同步VM | ms-duplex-number 应用于表单元素 | 没有对应项 | 如果value是数字格式就转换为数值,否则不做转换,然后再同步VM | ms-duplex 相当于ms-duplex-string | ms-duplex 在radio相当于ms-duplex-checked 在其他上相当于ms-duplex-string | 见上 |
注意:ms-duplex与ms-checked不能在同时使用于一个元素节点上。 注意:如果表单元素同时绑定了ms-duplex=xxx与ms-click或ms-change,而事件回调要立即得到这个vm.xxx的值,input[type=radio]是存在问题,它不能立即得到当前值,而是之前的值,需要在回调里面加个setTimeout。 有关ms-duplex的详细用法,大家可以通过这个页面进行学习。 <!DOCTYPE html>
<html>
<head>
<title>ms-duplex</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div ms-controller="box">
<ul>
<li><input type="checkbox" ms-click="checkAll" ms-checked="checkAllbool"/>全选</li>
<li ms-repeat="arr" ><input type="checkbox" ms-value="el" ms-duplex="selected"/>{{el}}</li>
</ul>
</div>
<script src="avalon.js" ></script>
<script>
var vm = avalon.define({
$id: "box",
arr : ["1", '2', "3", "4"],
selected : ["2", "3"],
checkAllbool : false,
checkAll : function() {
if (this.checked) {
vm.selected = vm.arr
} else {
vm.selected.clear()
}
}
})
vm.checkAllbool = vm.arr.length === vm.selected.length
vm.selected.$watch("length", function(n) {
vm.checkAllbool = n === vm.arr.size()
})
</script>
</body>
</html>
|
对于非radio, checkbox, select的控件,我们可以通过data-duplex-changed来指定一个回调,传参为元素的value值,this指向元素本身,要求必须有返回值。 <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>data-duplex-changed</title>
<script src="avalon.js"></script>
</head>
<body ms-controller="duplex">
<input ms-duplex="username" data-duplex-changed="callback">
<script type="text/javascript">
avalon.define({
$id: "duplex",
username : "司徒正美",
callback : function(val){
avalon.log(val)
avalon.log(this)
return this.value = val.slice(0, 10)//不能超过10个字符串
}
});
</script>
</body>
</html>
|
样式绑定(ms-css)用法为ms-css-name="value" 注意:属性值不能加入CSS hack与important! <!DOCTYPE html>
<html>
<head>
<title>by 司徒正美</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="../avalon.js"></script>
<script>
avalon.define({
$id: "test",
o: 0.5,
bg: "#F3F"// 不能使用CSS hack,如 bg : "#F3F\9\0"
})
</script>
<style>
.outer{
width:200px;
height: 200px;
position: absolute;
top:1px;
left:1px;
background: red;
z-index:1;
}
.inner{
width:100px;
height: 100px;
position: relative;
top:20px;
left:20px;
background: green;
}
</style>
</head>
<body ms-controller="test" >
<h3>在旧式IE下,如果父元素是定位元素,但没有设置它的top, left, z-index,那么为它设置透明时,
它的所有被定位的后代都没有透明</h3>
<div class="outer" ms-css-opacity="o" ms-css-background-color="bg" >
<div class="inner"></div>
</div>
</body>
</html>
|
数据绑定(ms-data)用法为ms-data-name="value", 用于为元素节点绑定HTML5 data-*属性。
布尔属性绑定1.3.5后,它们都吞入ms-attr-*这主要涉及到表单元素几个非常重要的布尔属性,即disabed, readyOnly, selected , checked, 分别使用ms-disabled, ms-enabled, ms-readonly, ms-checked, ms-selected。ms-disabled与ms-enabled是对立的,一个true为添加属性,另一个true为移除属性。
字符串属性绑定1.3.5后,除了ms-src, ms-href,其他都吞入ms-attr-*这主要涉及到几个非常常用的字符串属性,即href, src, alt, title, value, 分别使用ms-href, ms-src, ms-alt, ms-title, ms-value。它们的值的解析情况与其他绑定不一样,如果值没有{{}}插值表达式,那么就当成VM中的一个属性,并且可以与加号,减号混用, 组成表达式,如果里面有表达式,整个当成一个字符串。 <a ms-href="aaa + '.html'">xxxx</a>
<a ms-href="{{aaa}}.html">xxxx</a>
|
属性绑定(ms-attr)ms-attr-name="value",这个允许我们在元素上绑定更多种类的属性,如className, tabIndex, name, colSpan什么的。 |
使用 ms-attr-value="{{formData.title}}" 这种形式,为啥将model中的对象设置为{},对应的input的value不会自动设置为空呢?但是 label就可以:
<label class="control-label" for="title">{{formData.title}}</label>
<divms-controller="allocateListController" class="smain-sbar-right"><labelclass="control-label" for="title">{{formData.title}}</label><inputname="title1" ms-attr-value='formData.title' class="form-control" ></input><inputname="title2" ms-attr-value="{{formData.title}}" class="form-control" ></input></div><scripttype="text/javascript">require(["ui/smartgrid/avalon.smartgrid", "ui/dialog/avalon.dialog", "ui/kindeditor/avalon.kindeditor"], function() {setTimeout(function() {allocateListController.formData = {title: "11111"}}, 2000);setTimeout(function() {allocateListController.formData = {}}, 4000);setTimeout(function() {allocateListController.formData = {title: "2222"}}, 6000);var allocateListController = avalon.define({$id: "allocateListController",formData: {},}});</script>