在许多表单应用,我们经常遇到点击一个复选框(或下拉框)会引发旁边的复选框(或下拉框)发生改变,这种联动效果用avalon来做是非常简单的。在avalon里,存在各种绑定回调与$watch回调,完全满足你的需求。

下面是avalon所有绑定回调。

  1. data-duplex-changed,用于ms-duplex绑定,值改变后触发; 参数:当前元素的值
  2. data-include-loaded,用于ms-include-src绑定,模板加载后触发,可以在这里修改模板 参数:
    tmpl,vmodel1, vmodel2 ...
  3. data-include-rendered,用于ms-include, ms-include-src绑定,模板渲染好后触发; 没参数
  4. data-repeat-rendered,用ms-repeat绑定,当监控数组发生添加,删除,重排等操作时触发;
    参数:当前操作名("add","del","index","clear","move")
  5. data-with-sorted,用ms-repeat,
    ms-with绑定,赶对象渲染之前触发,要求输出一个字符串数组,对象的键值对会根据它依次输出; 参数:原对象的所有键名构成的数组
  6. data-with-rendered,用ms-with绑定,当目标对象输出页面后触发;
    参数:当前操作名("add","del","index","clear","move")
  7. data-each-rendered,用ms-each绑定,当监控数组发生添加,删除,重排等操作时触发;
    参数:当前操作名("add","del","index","clear","move")

在表单联动效果中,我们最常用的是data-duplex-change。事不宜迟,我们先来一个全选非全选例子吧。

<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="avalon.js"></script>
<script>
var model = avalon.define({
$id: "test",
data: [{checked: false}, {checked: false}, {checked: false}],
allchecked: false,
checkAll: function() {
var bool = this.checked
model.data.forEach(function(el) {
el.checked = bool
})
},
checkOne: function() {
if (!this.checked) {
model.allchecked = false
} else {//avalon已经为数组添加了ecma262v5的一些新方法
model.allchecked = model.data.every(function(el) {
return el.checked
})
}
}
})
</script>
</head>
<body>
<table ms-controller="test" border="1">
<tr>
<td><input type="checkbox" ms-duplex-radio="allchecked" data-duplex-changed="checkAll"/>全选</td>
</tr>
<tr ms-repeat="data">
<td><input type="checkbox" ms-duplex-radio="el.checked" ms-data-index=$index data-duplex-changed="checkOne"/>xxxxxxxxxxxx</td>
</tr>
</table>
</body>
</html>


我们仔细分析其源码,allchecked是用来控制最上面的复选框的打勾情况,数组中的checked是用来控制下面每个复选框的下勾情况。由于是使用ms-duplex,因此会监听用户行为,当复选框的状态发生改变时,就会触发data-duplex-change回调,将当前值传给回调。但这里我们不需要用它的value值,只用它的checked值。最上面的复选框对应的回调是checkAll,它是用来更新数组的每个元素的checked属性,因此一个forEach循环赋值就是。下面的复选框对应的checkOne,它们是用来同步最上面的复选框,只要它们有一个为false上面的复选框就不能打勾,当它们被打勾了,它们就得循环整个数组,检查是否所有元素都为true,是才给上面的checkall属性置为true。

再看用ms-duplex与$watch实现表格排序效果。

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="../avalon.js" ></script>
<script>
if (!Date.now) {//fix 旧式IE
Date.now = function() {
return new Date - 0;
}
}
var model = avalon.define({
$id: "test",
selected: "name",
options: ["name", "size", "date"],
trend: 1,
data: [
{name: "aaa", size: 213, date: Date.now() + 20},
{name: "bbb", size: 4576, date:Date.now() - 4},
{name: "ccc", size: 563, date: Date.now() - 7},
{name: "eee", size: 3713, date: Date.now() + 9},
{name: "555", size: 389, date: Date.now() - 20}
]
})
model.$watch("selected", function(v) {
var t = parseFloat(model.trend)
model.data.sort(function(a, b) {
if (v === "name") {
return t * a[v].localeCompare(b[v])
} else {
var ret = a[v] > b[v] ? 1 : -1
return t * ret
}
})
})
model.$watch("trend", function(t) {
var v = model.selected, t = parseFloat(t)
model.data.sort(function(a, b) {
var ret = a[v] > b[v] ? 1 : -1
return t * ret
})
}) </script>
</head>
<body ms-controller="test">
<div style="color:red">
<p>本例子用于显示如何做一个简单的表格排序</p>
<p>ms-repeat="array"相当于ms-repeat-el="array" </p>
</div>
<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同步selected, trend属性,而selected, trend的值改变时,就会触发对应的$watch回调,然后通过监控数组的sort方法实现表格排序。从而也可以看出监控数组与ms-repeat的强大。

我们再来一个文本域与下拉框的联动例子,它只用到ms-duplex,不过两个控件都是绑定同一个属性。

<!DOCTYPE html>
<html>
<head>
<script src="avalon.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
avalon.define({
$id: "fruit",
options: ["苹果", "香蕉", "桃子", "雪梨", "葡萄", "哈蜜瓜", "橙子", "火龙果", "荔技", "黄皮"],
selected: "桃子"
})
</script>
</head>
<body ms-controller="fruit">
<h3>文本域与下拉框的联动</h3>
<input ms-duplex="selected" />
<select ms-duplex="selected" >
<option ms-repeat-option="options" ms-value="option" >{{option}}</option>
</select>
</body>
</html>

我们再看一个超级复杂的三级联动下拉框。

<!DOCTYPE html>
<html>
<head>
<script src="avalon.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
var map = {
"中国": ["江南四大才子", "初唐四杰", "战国四君子"],
"日本": ["日本武将", "日本城堡", "幕府时代"],
"欧美": ["三大骑士团", "三大魔幻小说", "七大奇迹"],
"江南四大才子": ["祝枝山", "文征明", "唐伯虎", "周文宾"],
"初唐四杰": ["王勃", "杨炯", "卢照邻", "骆宾王"],
"战国四君子": ["楚国春申君黄歇", "齐国孟尝君田文", "赵国平原君赵胜", "魏国信陵君魏无忌"],
"日本武将": ["织田信长", "德川家康", "丰臣秀吉"],
"日本城堡": ["安土城", "熊本城", "大坂城", "姬路城"],
"幕府时代": ["镰仓", "室町", "丰臣", "江户"],
"三大骑士团": ["圣殿骑士团", "医院骑士团", "条顿骑士团"],
"三大魔幻小说": ["冰与火之歌", "时光之轮", "荆刺与白骨之王国"],
"七大奇迹": ["埃及胡夫金字塔", "奥林匹亚宙斯巨像", "阿尔忒弥斯月神殿", "摩索拉斯陵墓", "亚历山大港灯塔", "巴比伦空中花园", "罗德岛太阳神巨像"]
} avalon.define("linkage", function(vm) {
vm.first = ["中国", "日本", "欧美"]
vm.second = map[vm.first[1]].concat()
vm.third = map[vm.second[0]].concat()
vm.firstSelected = "日本"
vm.secondSelected = "日本武将"
vm.thirdSelected = "织田信长" vm.$watch("firstSelected", function(a) {
vm.second = map[a].concat()
vm.secondSelected = vm.second[0]
})
vm.$watch("secondSelected", function(a) {
vm.third = map[a].concat()
vm.thirdSelected = vm.third[0]
})
})
</script>
</head>
<body >
<div ms-controller="linkage">
<h3>下拉框三级联动</h3>
<select ms-duplex="firstSelected" >
<option ms-repeat="first" ms-value="el" >{{el}}</option>
</select>
<select ms-duplex="secondSelected" >
<option ms-repeat="second" ms-value="el" >{{el}}</option>
</select>
<select ms-duplex="thirdSelected" >
<option ms-repeat="third" ms-value="el" >{{el}}</option>
</select>
</div>
</body>
</html>


由于存在三个下拉框,需要的数据比较多,因此我们搞了一个map来存放它们。。然后我们先初始化第一个下拉框,vm.first = [”中国”, ”日本”, ”欧美”],默认是选中第二个(firstSelected)。然后初始化第二个下拉框,需要从map拷贝一份赋给second,然后再默认其选中项,然后是第三个下拉框……

接着是通过$watch回调实现联动,不用管第三个下拉框(因为它总是被动的),那么只有监听firstSelected, secondSelected。每次变化都需要从map找到正确的数组,复制一次赋给second与third,并且默认选中第一项。

最后奉上一用户做的多级联动效果,自己细细品味吧。

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="avalon.js"></script>
<script> var data = [
{"id": 0, "name": "1公司", "grade": -1, "parentid": "-1"},
{"id": 1, "name": "广东公司", "grade": 0, "parentid": "0"},
{"id": 2012300001, "name": "广州1分公司", "grade": 1, "parentid": 1},
{"id": 200000000, "name": "广州分公司", "grade": 1, "parentid": 1},
{"id": 4050, "name": "天河分公司", "grade": 2, "parentid": 200000000},
{"id": 999182, "name": "工业园营销服务中心", "grade": 3, "parentid": 4050},
{"id": 4174, "name": "南沙分公司", "grade": 2, "parentid": 200000000},
{"id": 10121, "name": "南沙营销服务中心", "grade": 3, "parentid": 4174},
]
var a = avalon.define("test", function(vm) {
vm.searchForm = [];
vm.setSearchFormInit = function(currNode) {
var childNodes = vm.getChildOrg(currNode);
if (childNodes.length)
vm.searchForm = [childNodes];
};
vm.setSearchForm = function(index) {
//vm.searchForm._del(index,10)//在选中某个select后,取得index,删除它后边的所有成员
avalon.log("删除第" + index + "个元素后的所有成员")
a.searchForm.removeAll(function(arr, i) {
if (i > index)
return true;
return false;
});
var currNode = this.value;
var childNodes = vm.getChildOrg(currNode);
if (childNodes.length)
vm.searchForm.push(childNodes);
};
vm.getChildOrg = function(id) {
var retList = [];
for (var i = 0; i < data.length; i++) {
var elem = data[i]
if (elem.parentid != id)
continue;
retList.push({
id: elem.id,
name: elem.name,
parentid: elem.parentid
});
}
return retList;
}
})
a.setSearchFormInit(0)
</script>
</head>
<body ms-controller="test">
<div ms-repeat-form="searchForm">
<select ms-change="setSearchForm($index)">
<option></option>
<option ms-repeat-el="form" ms-value="el.id">{{el.name}}</option>
</select>
</div>
</body>
</html>

迷你MVVM框架 avalonjs 学习教程12、数据联动的更多相关文章

  1. 迷你MVVM框架 avalonjs 学习教程19、avalon历史回顾

    avalon最早发布于2012.09.15,当时还只是mass Framework的一个模块,当时为了解决视图与JS代码的分耦,参考knockout开发出来. 它的依赖收集机制,视图扫描,绑定的命名d ...

  2. 迷你MVVM框架 avalonjs 学习教程1、引入avalon

    avalon是国内最强大的MVVM框架,没有之一,虽然淘宝KISSY团队也搞了两个MVVM框架,但都无疾而终.其他的MVVM框架都没几个.也只有外国人与像我这样闲的架构师才有时间钻研这东西.我很早之前 ...

  3. 迷你MVVM框架 avalonjs 学习教程18、一步步做一个todoMVC

    大凡出名的MVC,MVVM框架都有todo例子,我们也搞一下看看avalon是否这么便宜. 我们先从react的todo例子中扒一下HTML与CSS用用. <!doctype html> ...

  4. 迷你MVVM框架 avalonjs 学习教程3、绑定属性与扫描机制

    在MVVM框架中,你都会看到页面定了许多奇怪的属性,比如knockout的data-☆,angular的ng-☆,avalon的ms-☆,此外还有一些只写文本节点上的双花括号,它们统称为指令.ms-☆ ...

  5. 迷你MVVM框架 avalonjs 学习教程4、数据填充

    MVVM是前端的究极解决方案,你们可能用过jQuery,但那个写的代码不易维护:你们可以听过说requirejs与seajs,传说中的模块开发,加载器,但它们的最终目标是打包:你们可能听过unders ...

  6. 迷你MVVM框架 avalonjs 学习教程7、数据缓存

    jQuery的许多功能都可以通过avalon的绑定属性来处理,如click方法对应ms-click,css方法对应ms-css,toggle方法对应ms-visible,它的数据缓存功能avalon也 ...

  7. 迷你MVVM框架 avalonjs 学习教程20、路由系统

    SPA的成功离开不这三个东西,分层架构,路由系统,储存系统.分层架构是我们组织复杂代码的关键,这里特指MVVM的avalon:路由系统是将多个页面压缩在一个页面的关键:储存系统特指本地储存,是安全保存 ...

  8. 迷你MVVM框架 avalonjs 学习教程11、循环操作

    avalon是通过ms-repeat实现对一组数据的批量输出.这一组数据可以是一个数组,也可以是一个哈希(或叫对象).我们先从数组说起吧. 第二节就说,凡是定义在VM中的数组,如果没有以$开头或者没放 ...

  9. 迷你MVVM框架 avalonjs 学习教程16、过滤器

    avalon的过滤器是参考自angular与rivets.它也被称做管道文本过滤器,它的处理对象只能是文本(字符串),它只能用在文本绑定中,并且只能是双花括号形式.下面是各大家的过滤器比较: rive ...

随机推荐

  1. JMeter--使用URL回写来处理用户会话

    如果测试的Web应用系统使用URL回写而非Cookie来保存会话信息,那么测试人员需要做一些额外的工作来测试web站点 为了正确回应URL回写,JMeter需要解析从服务器收到的HTML,并得到唯一的 ...

  2. Mysql 性能优化1 硬件设备的选择

    --------------------------------------------目录------------------------------------------------- • 我们 ...

  3. 【Spring学习笔记-MVC-8】SpringMVC之类型转换Converter

    作者:ssslinppp       1. 摘要 在spring 中定义了3中类型转换接口,分别为: Converter接口              :使用最简单,最不灵活: ConverterFa ...

  4. Logstash之四:配置说明

    logstash配置文件包含三个配置部分: 分别为:input{}.filter{}.output{}.{} 定义区域,区域内可以定义一个或多个插件,通过插件对数据进行收集,加工处理,输出. 在{}配 ...

  5. java学习——构造类

    package my_project; public class my_first_class { public static void main(String[] args) { // TODO A ...

  6. java实验三——求平均数,数组排序(有关java保留小数位数,由于编译器版本未到1.5导致的报错format函数第二个参数不对,要求是Object[])

    package hello; import java.util.Arrays; public class 实验三更正版 { public static void main(String[] args) ...

  7. [转]C#API 实现锁屏+关屏

    http://www.cnblogs.com/1971ruru/archive/2010/05/20/1740216.html public Form1( bool aLock ) { if (aLo ...

  8. 1077 Kuchiguse (20 分)

    1077 Kuchiguse (20 分) The Japanese language is notorious for its sentence ending particles. Personal ...

  9. ThinkPHP框架学习摘要

    框架在linux与win下区别 1.文件权限设置: 2.大小写不规范: 学习框架的基本思路 : 1.如何收入并配置框架: 2.Controller的命名规范与书写规范: 3.Model的命名规范与书写 ...

  10. 组件Slate教程 & UMG widget构造初始化函数中获取其内部组件

    转自:http://aigo.iteye.com/blog/2296218 目的:在自定义的Widget初始化完毕后,获取其内部的button.combo等UMG组件的C++指针. 这里我们新建了一个 ...