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

MVVM是前端的究极解决方案,你们可能用过jQuery,但那个写的代码不易维护;你们可以听过说requirejs与seajs,传说中的模块开发,加载器,但它们的最终目标是打包;你们可能听过underscope,那是一个工具集;你们可以听说过ejs,Mustache、HandlebarsJS等模板引擎,它们是用来替代字符串拼接……凡此种种,它们在我们的业务开发中只是很少的部分,带来的帮助也很有限。前端开发,贯彻始终的是如何将后端的数据显示出来,将用户的输入格式化送到后端,都离不开DOM操作,而DOM操作正是许多新手或从后端过来的人所害怕。相比于JS的那点语法,DOM是最庞杂的,三次浏览器大战留下的遗患至今没有消弥,到处是地雷,因此我们怎么放心让新人去趟这祸水呢。jQuery为开发者发一个水泡,让你们淹不死。但最佳方式,就是把这些腐败沼泽都填了。avalon做到了,纯数据操作的时代到来了。

前三节就分别介绍了作用域,ViewModel,绑定属性什么的,它们是我们的主角。其中ViewModel是我们操作的主体,绑定属性是让我们脱离DOM操作的关键。所有对ViewModel的操作,最终交由绑定属性实现各种DOM功能。DOM功能是一个很范的概念,比如添加删除类名,移除节点,让某个元素看不见,为元素添加某个属性或某个事件……今天我们介绍的就是最常用数据填充功能,让后端的数据在页面展示出来。MVVM是如此强大,估计今明年,你们会越来越频繁地看到有关前端MVVM的主题分题,PPT。作为一个简单的示例,它们务必包含数据填充功能的展示。

数据填充是avalon最简单的功能,将数据打印到页面上。这是所有后端模板最基本的功能,然后加上each, if, include等语法,实现更精细的制定。avalon通过绑定属性,其实将整个页面变成一个动态模板(详看这里)。将数据输出到页面涉及到以下指令。

  • {{prop}}
  • {{prop|html}}
  • ms-text
  • ms-html
  • ms-value
  • ms-duplex

{{prop}}是最简单实用的指令,什么helloworld用它做最适合了。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <script src="avalon.js"></script>
        <script>
            avalon.define({
                $id: "test",
                word: "Hello Avalon"
            })
        </script>
    </head>
    <body>
        <div ms-controller="test">
            <h1>{{word}}!!!!!</h1>
        </div>
    </body>
</html>

{{prop | html}}其实是加一个过滤器,也只有文本节点中的插值表达式可以加各种过滤器实现各种功能。html过滤器就是将此字符串转换HTML节点再插入当前位置。不过这个{{prop|html}},框架是对它开了小灶,允许它本来就是一个元素节点或NodeList。

ms-text与ms-html其实就是{{prop}}、{{prop|html}}的真身,框架内部都是走同一处理函数。不过ms-text、 ms-html作为一个绑定属性,必须附于元素节点之上,因此没有前者那么方便。


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <script src="avalon.js"></script>
        <script>
            avalon.define("test", function(vm) {
                vm.text = "<b> 1111  </b>"
            })
        </script>
    </head>
    <body>
        <div ms-controller="test">
            <div><em>用于测试是否被测除</em>xxxx{{text}}yyyy</div>
            <div><em>用于测试是否被测除</em>xxxx{{text|html}}yyyy</div>
            <div ms-text="text"><em>用于测试是否被测除</em>xxxx yyyy</div>
            <div ms-html="text"><em>用于测试是否被测除</em>xxxx yyyy</div>
        </div>
    </body>
</html>

此外,我们还可以通过config方法,更改插值表达式的界定符,因为{{}}可能被其他框架的模板所占用。建议界定符的长度大于1,不要设置为>>这样的位操作符。比如在DOMReady之前,我们调用如下语句:

avalon.config({
   interpolate: ["<%", "%>"] //  要求openTag 不等于closeTag就能配置成功
})

像上面那样,由于网速慢把插值表达式暴露出来的问题, 我们可以定义这样一个样式规则进行处理,这有点类于angularjs的ng-cloak指令,在扫描之前起着羞丑布的作用。当扫描过后,框架会去掉绑定属性,及ms-controller、ms-important这两个类名,它们就显示出来了。

.ms-controller, .ms-important{visibility:hidden}

上述四种指令是用在文本节点上,但数据还能通过表单元素的value值显示出来,于是有了ms-value指令。ms-value为了应对复杂的显示,也支持插值表达式,但里面不能使用过滤器。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <script src="avalon.js"></script>
        <script>
            avalon.define({
                $id: "test",
                text: "<b> 1111  </b>"
            })
        </script>
    </head>
    <body>
        <div ms-controller="test">
            <input ms-value="text"/>
            <textarea ms-value="xxxxxxxx{{text+‘!!‘}}yyyyyyyy"/></textarea>
        </div>
    </body>
</html>

上面的功能,后端模板与前端模板也能做到,但ms-duplex就逆天了。它是avalon实现双向绑定的一个重要绑定。双向绑定通俗说,当我们修改ViewModel的属性,通过Object.defineProperty重写属性的setter,getter同步视图,而在视图上偷偷绑定一些input、click、change事件,将元素的value同步到ViewModel上。ms-duplex就是这样干,也意味着它只对表单元素生效。avalon为文本域,文本区,密码域这三个控件绑定了input事件,换言之,用户每改一个字符都会立即发生同步,当然用户可以在元素定义data-duplex-event=”change”属性,就可以改成change事件。对于单选框,复选框,下拉条是绑定了change事件。

在IE6-8下,没有input事件,avalon使用onpropertychange事件,单选框复选框的change事件有BUG,改用click事件,总而言之,avalon设法让旧式IE与W3C浏览器保持一致。

如果用户想在内容发生改变后执行某一回调,avalon也提供了data-duplex-changed回调。此外,用户也可以在VM上使用$watch回调进校正。因此,有了ms-duplex做数据验证是非常简单的。

我们还可以在元素节点上定义data-duplex-observe=”false”来禁止双向同步。

ms-duplex还可以接第三个参数,总括起来,它们的语法如下:

ms-duplex=”prop” 当元素为text, password, textarea时,要求prop为一个字符串,当我们改动它的内容时,avalon就会将此元素的value值赋给prop(在默认情况下,是使用input事件进行绑定,即每改动一个字符,都会进行同步,大家也可以指定data-duplex-event="change",改用change事件进行绑定) 当元素为radio时,要求prop为一个布尔, 当我们改动它的内容时,avalon就会将此元素的checked值(布尔)赋给prop 当元素为checkbox时,要求prop为一个数组, 当我们改动它的内容时,avalon就会将此元素的value值push进prop 当元素为select时,要求prop为一个字符串或数组(视multiple的值), 当我们选中它的某一个项时,avalon就会将此option元素的value值或text值(没有value时)push进prop。

ms-duplex-text=”prop” 只能用于radio,用于模拟text控件的行为, 要求prop为一个字符串,当我们选中某一个radio时,avalon就会将此元素的value值赋给prop 用于实现多选一。

ms-duplex-radio=”prop” 只能用于checkbox,用于模拟radio控件的行为, 要求prop为一个布尔,当我们选中某一个checkbox时,avalon就会将此元素的checked值(布尔)赋给prop 多用于实现GRID中的全选/全不选功能

ms-duplex-bool=”prop” 只能用于radio, 要求prop为一个布尔,并且元素的value为“true”或“false”,当我们选中某一个radio时,avalon就会将此元素的value转换为布尔,赋给对应的prop。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="avalon.js"></script>
        <script>
            avalon.define({
                $id: "test",
                aaa: {
                    xxx: "444",
                    yyy: "555"
                },
                bbb: "yyy",
                zzz: "text"
            })
        </script>
    </head>
    <body ms-controller="test">
        <input ms-duplex="aaa[‘xxx‘]"><br/>
        <input ms-duplex="aaa[bbb]"><br/>
        <input ms-duplex="zzz" ms-data-duplex-observe="zzz"/>当这里的值变成false,就会禁止双向同步
        <p>{{aaa.xxx}}</p>
        <p>{{aaa.yyy}}</p>
        <p>{{zzz}}</p>
    </body>
</html>

这里有更多ms-duplex的例子。弄懂它们就可以处理大多数表单需求了,然后你就会觉得生活变美好了一些。这快感正如我们一开始从原生JS转到jQuery的那样。时代总是在进步的,早期了解MVVM,早期摆脱DOM的桎梏!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。