类名切换(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>
<
div
ms-controller="allocateListController" class="smain-sbar-right">
<
label
class="control-label" for="title">{{formData.title}}</
label
>
<
input
name="title1" ms-attr-value='formData.title' class="form-control" ></
input
>
<
input
name="title2" ms-attr-value="{{formData.title}}" class="form-control" ></
input
>
</
div
>
<
script
type="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
>