在许多表单应用,我们经常遇到点击一个复选框(或下拉框)会引发旁边的复选框(或下拉框)发生改变,这种联动效果用avalon来做是非常简单的。因为avalon拥有经典MVVM框架的一大利器,双向绑定!绝大部分的指令是从vm单向拍到页面,而双向绑定,则通过监听元素的value值变化,反向同步到vm中。如果没有这种机制,则需要引入额外的机制(flux云云)来处理此事。

avalon中,双向绑定是由双工指设,ms-duplex实现的。这个指令在1.0中已经不断增强,到2.0,它的服务对象已经不局限于表单元素,还扩展到可编辑元素(contenteditable=true)上了。

此外ms-duplex还可以与新加入的ms-validate指令一起使用。因此双工指令是集成数据转换,数据格式化,数据验证,光标处理4大功能。

数据转换与之前1.5一样,使用四大转换器

  1. ms-duplex-string="@aaa"
  2. ms-duplex-number="@aaa"
  3. ms-duplex-boolean="@aaa"
  4. ms-duplex-checked="@aaa"

前三个是将元素的value值转换成string, number, boolean(只有为'false'时转换为false),最后是根据当前元素(它只能是radio或checkbox)的checked属性值转换为vm对应属性的值。

它们都是放在属性名上。当数据从元素节点往vmodel同步时,转换成预期的数据。

数据格式化是放在属性值时,以过滤器形式存在,如

  1. ms-duplex='@aaa | uppercase'
  2. ms-duplex='@aaa | date('YYYY:MM:dd')'

此外还存在两个控制同步时机的过滤器,change与debounce。

change过滤器相当于之前的data-duplex-event="change".

debounce是对频繁输入进行节流处理。它既不像那oninput事件那样密集(由于使用了虚拟DOM,每一个字符,都会重新短成一个全新的虚拟DOM树),也不像onchange事件那么滞后。这在自动元素的suggest组件中非常有用。debounce可以传参,为毫秒数

  1. ms-duplex='@aaa | debounce(300)'

然后是数据验证,这必须在所有表单元素的上方,加上ms-validate才会生效。这时每个表单元素要加上data-duplex-validator.

  1. <form ms-validate="@validation">
  2. <input ms-duplex='@aaa'
  3. data-validators='require,email,maxlength'
  4. data-maxlength='4'
  5. data-maxlength-message='太长了' >
  6. </form>

最后是光标处理,目的是确保光标不会一下子跑到最前还是最后。

除此之后,ms-duplex还有一个回调,data-duplex-changed,用于与事件绑定一样,默认第一个参数为事件对象。如果传入多个参数,那么使用$event为事件对象占位。

现在我们来一些实际的例子!

全选与非全选

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>TODO supply a title</title>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width">
  7. <script src="./dist/avalon.js"></script>
  8. <script>
  9. var vm = avalon.define({
  10. $id: "test",
  11. data: [{checked: false}, {checked: false}, {checked: false}],
  12. allchecked: false,
  13. checkAll: function (e) {
  14. var checked = e.target.checked
  15. vm.data.forEach(function (el) {
  16. el.checked = checked
  17. })
  18. },
  19. checkOne: function (e) {
  20. var checked = e.target.checked
  21. if (checked === false) {
  22. vm.allchecked = false
  23. } else {//avalon已经为数组添加了ecma262v5的一些新方法
  24. vm.allchecked = vm.data.every(function (el) {
  25. return el.checked
  26. })
  27. }
  28. }
  29. })
  30. </script>
  31. </head>
  32. <body>
  33. <table ms-controller="test" border="1">
  34. <tr>
  35. <td><input type="checkbox"
  36. ms-duplex-checked="@allchecked"
  37. data-duplex-changed="@checkAll"/>全选</td>
  38. </tr>
  39. <tr ms-for="($index, el) in @data">
  40. <td><input type="checkbox" ms-duplex-checked="el.checked" data-duplex-changed="@checkOne" />{{$index}}::{{el.checked}}</td>
  41. </tr>
  42. </table>
  43. </body>
  44. </html>

我们仔细分析其源码,allchecked是用来控制最上面的复选框的打勾情况,数组中的checked是用来控制下面每个复选框的下勾情况。由于是使用ms-duplex,因此会监听用户行为,当复选框的状态发生改变时,就会触发data-duplex-changed回调,将当前值传给回调。但这里我们不需要用它的value值,只用它的checked值。

最上面的复选框对应的回调是checkAll,它是用来更新数组的每个元素的checked属性,因此一个forEach循环赋值就是。

下面的复选框对应的checkOne,它们是用来同步最上面的复选框,只要它们有一个为false上面的复选框就不能打勾,当它们被打勾了,它们就得循环整个数组,检查是否所有元素都为true,是才给上面的checkall属性置为true。

现在 我们学了循环指令,结合它来做一个表格看看。现在有了强大无比的orderBy, limitBy, filterBy, selectBy。我们做高性能的大表格是得心应手的!

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <script src="./dist/avalon.js" ></script>
  7. <script>
  8. if (!Date.now) {//fix 旧式IE
  9. Date.now = function() {
  10. return new Date - 0;
  11. }
  12. }
  13. var model = avalon.define({
  14. $id: "test",
  15. selected: "name",
  16. options: ["name", "size", "date"],
  17. trend: 1,
  18. data: [
  19. {name: "aaa", size: 213, date: Date.now() + 20},
  20. {name: "bbb", size: 4576, date:Date.now() - 4},
  21. {name: "ccc", size: 563, date: Date.now() - 7},
  22. {name: "eee", size: 3713, date: Date.now() + 9},
  23. {name: "555", size: 389, date: Date.now() - 20}
  24. ]
  25. })
  26. </script>
  27. </head>
  28. <body ms-controller="test">
  29. <div style="color:red">
  30. <p>本例子用于显示如何做一个简单的表格排序</p>
  31. </div>
  32. <p>
  33. <select ms-duplex="@selected">
  34. <option ms-for="el in @options">{{el}}</option>
  35. </select>
  36. <select ms-duplex-number="@trend">
  37. <option value="1">up</option>
  38. <option value="-1">down</option>
  39. </select>
  40. </p>
  41. <table width="500px" border="1">
  42. <tbody >
  43. <tr ms-for="el in @data | orderBy(@selected, @trend)">
  44. <td>{{el.name}}</td> <td>{{el.size}}</td> <td>{{el.date}}</td>
  45. </tr>
  46. </tbody>
  47. </table>
  48. </body>
  49. </html>

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

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script src="./dist/avalon.js"></script>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6. <script>
  7. avalon.define({
  8. $id: "fruit",
  9. options: ["苹果", "香蕉", "桃子", "雪梨", "葡萄", "哈蜜瓜", "橙子", "火龙果", "荔技", "黄皮"],
  10. selected: "桃子"
  11. })
  12. </script>
  13. </head>
  14. <body ms-controller="fruit">
  15. <h3>文本域与下拉框的联动</h3>
  16. <input ms-duplex="@selected" />
  17. <select ms-duplex="@selected" >
  18. <option ms-for="el in @options" ms-attr="{value: el}" >{{el}}</option>
  19. </select>
  20. </body>
  21. </html>

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script src="./dist/avalon.js"></script>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6. <script>
  7. var map = {
  8. "中国": ["江南四大才子", "初唐四杰", "战国四君子"],
  9. "日本": ["日本武将", "日本城堡", "幕府时代"],
  10. "欧美": ["三大骑士团", "三大魔幻小说", "七大奇迹"],
  11. "江南四大才子": ["祝枝山", "文征明", "唐伯虎", "周文宾"],
  12. "初唐四杰": ["王勃", "杨炯", "卢照邻", "骆宾王"],
  13. "战国四君子": ["楚国春申君黄歇", "齐国孟尝君田文", "赵国平原君赵胜", "魏国信陵君魏无忌"],
  14. "日本武将": ["织田信长", "德川家康", "丰臣秀吉"],
  15. "日本城堡": ["安土城", "熊本城", "大坂城", "姬路城"],
  16. "幕府时代": ["镰仓", "室町", "丰臣", "江户"],
  17. "三大骑士团": ["圣殿骑士团", "医院骑士团", "条顿骑士团"],
  18. "三大魔幻小说": ["冰与火之歌", "时光之轮", "荆刺与白骨之王国"],
  19. "七大奇迹": ["埃及胡夫金字塔", "奥林匹亚宙斯巨像", "阿尔忒弥斯月神殿", "摩索拉斯陵墓", "亚历山大港灯塔", "巴比伦空中花园", "罗德岛太阳神巨像"]
  20. }
  21. var vm = avalon.define({
  22. $id: 'linkage',
  23. first: ["中国", "日本", "欧美"],
  24. second: map['日本'].concat(),
  25. third: map['日本武将'].concat(),
  26. firstSelected: "日本",
  27. secondSelected: "日本武将",
  28. thirdSelected: "织田信长"
  29. })
  30. vm.$watch("firstSelected", function (a) {
  31. vm.second = map[a].concat()
  32. vm.secondSelected = vm.second[0]
  33. })
  34. vm.$watch("secondSelected", function (a) {
  35. vm.third = map[a].concat()
  36. vm.thirdSelected = vm.third[0]
  37. })
  38. </script>
  39. </head>
  40. <body >
  41. <div ms-controller="linkage">
  42. <h3>下拉框三级联动</h3>
  43. <select ms-duplex="@firstSelected" >
  44. <option ms-for="el in @first" ms-attr="{value:el}" >{{el}}</option>
  45. </select>
  46. <select ms-duplex="@secondSelected" >
  47. <option ms-for="el in @second" ms-attr="{value:el}" >{{el}}</option>
  48. </select>
  49. <select ms-duplex="@thirdSelected" >
  50. <option ms-for="el in @third" ms-attr="{value:el}" >{{el}}</option>
  51. </select>
  52. </div>
  53. </body>
  54. </html>



这里的技巧在于使用$watch回调来同步下一级的数组与选中项。注意,使用concat方法来复制数组。

avalon2学习教程11数据联动的更多相关文章

  1. avalon2学习教程12数据验证

    avalon2砍掉了不少功能(如ms-include,ms-data),腾出空间加了其他更有用的功能.数据验证就是其中之一.现在avalon2内置的验证指令是参考之前的oniui验证框架与jquery ...

  2. avalon2学习教程 03数据填充

    数据填充是一个模版最基础的功能,直接从JSON(vm)取出数据,放到适当的位置上.在静态模板中,不区分文本与HTML,只看你的字符串是否有< >来决定生成文本节点与元素节点.但MVVM中, ...

  3. ASP.NET MVC 5 学习教程:数据迁移之添加字段

    原文 ASP.NET MVC 5 学习教程:数据迁移之添加字段 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符 ...

  4. Tensorflow学习教程------读取数据、建立网络、训练模型,小巧而完整的代码示例

    紧接上篇Tensorflow学习教程------tfrecords数据格式生成与读取,本篇将数据读取.建立网络以及模型训练整理成一个小样例,完整代码如下. #coding:utf-8 import t ...

  5. avalon2学习教程13组件使用

    avalon2最引以为豪的东西是,终于有一套强大的类Web Component的组件系统.这个组件系统媲美于React的JSX,并且能更好地控制子组件的传参. avalon自诞生以来,就一直探索如何优 ...

  6. avalon2学习教程02之vm

    avalon2的vm是一个非常重要的东西,其设计原型最初脱胎于knockout.js,但到avalon1.6中,终于寻得自己的方案,更精简,更易用,更魔幻. vm是一种特殊的数据结构,看起来像普通对象 ...

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

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

  8. avalon2学习教程15指令总结

    avalon的指令在上一节已经全部介绍完毕,当然有的语焉不详,如ms-js.本节主要总结我对这方面的思考与探索. MVVM的成功很大一语分是来自于其指令,或叫绑定.让操作视图的功能交由形形式式的指令来 ...

  9. avalon2学习教程09循环操作

    avalon2的循环指令的用法完全改变了.avalon最早期从knockout那样抄来ms-each,ms-with,分别用于数组循环与对象循环.它们都是针对元素内容进行循环.后来又从angular那 ...

随机推荐

  1. IOS开发-当遇到tableView整体上移时的解决方案

    方案一在使用了navigationController后,当界面进行跳转往返后,时而会出现tableView上移的情况,通常会自动上移64个像素,那么这种情况,我们可以关闭tableView的自动适配 ...

  2. python学习:函数的学习

    我们写东东的时候,往往有一些东西要频繁去复用,那么每个功能是10行代码,复用2次就是20行,这样看来我们的程序如果频繁利用某些代码的话,那么会是我们开发的东西越来越臃肿.那么好的方法有没有呢,那就是函 ...

  3. C++ 迭代器模式实现

    STL模板库中有大量迭代器实现,这些迭代器隔离了算法实现与访问接口,我们也可以编写属于自己的迭代器.STL中的迭代器均继承至一个通用迭代器接口: template <class _Categor ...

  4. Neo4j 两种索引Legacy Index与Schema Index区别

    Legacy Indexes 在Neo4j 2.0版本之前,Legacy index被称作indexes.这个索引是通过外部图存储在外的Lucene实现,允许“节点”和“联系”以key:value键值 ...

  5. Thrift 个人实战--RPC服务的发布订阅实现(基于Zookeeper服务)

    前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...

  6. 030. asp.net中DataList数据绑定跳转(两种方式)的完整示例

    前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.as ...

  7. 【C】 01 - 再学C语言

    “C语言还用再学吗?嵌入式工程师可是每天都在用它,大家早就烂熟于心,脱离语言这个层面了”.这样说不无道理,这门古老的语言以其简单的语法.自由的形式的而著称.使用C完成工作并不会造成太大困扰,所以很少有 ...

  8. [轉]Android Libraries 介紹 - Butter knife

    原文地址 Butter Knife 簡介 Butter Knife - Field and method binding for Android views.助你簡化程式碼,方便閱讀. 使用方法 開發 ...

  9. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  10. [转载] 【Shiro】Apache Shiro架构之实际运用(整合到Spring中)

    写在前面:前面陆陆续续对Shiro的使用做了一些总结,如题,这篇博文主要是总结一下如何将Shiro运用到实际项目中,也就是将Shiro整到Spring中进行开发.后来想想既然要整,就索性把Spring ...