您的位置:首页 > 其它

利用avalon 实现一个简单的成绩单

2015-05-16 19:01 309 查看


利用avalon 实现一个简单的成绩单

本文的灵感是来自Halower的这篇博文,他是使用knockout与jQuery实现的。不过我觉得MVVM本来就强大的事件绑定功能,因此用jQuery
是多此一举。另,他也用了一些面向对象的写法。我个人认为,纯数据就该好好当纯数据,作为数据模型(M)而存在,想操作数据,则交由视图模型(VM)。在angularjs流行的一些成规,都是要求大家不要自己操作DOM,DOM是框架自行帮你偷偷搞定。这也与avalon一直提倡的“操作数据即操作DOM”的理念相符。由于avalon巧妙地利用了Object.defineProperty, __defineSetter__, __defineGetter__, VBScript等方法把等于号(=)重载了,因此与视图的同步就变得比其他MVVM更隐秘神奇。那么接着下来,让我们看看avalon是如何实现这个功能吧。
首先是视图层,里面的绑定属性其实可以在VM中的属性定了下来再添加。这也涉及MVVM另一个优势,分离关注点,因此切图与JS编程可以同时进行。由于JS代码不进行DOM操作,页面长得怎么样也无所谓,我又不需要选择器引擎!

<
div
ms-controller
=
"grid"
class
=
"grid"
>
<
div
>
<
p
>
<
input
ms-duplex
=
"id"
>
<
input
ms-duplex
=
"name"
>
<
input
ms-duplex
=
"score"
data-duplex-event
=
"change"
></
p
>
<
p
><
button
ms-click
=
"add"
>
add</
button
></
p
>
</
div
>
<
p
>共{{array.size()}}条------------------合计{{total}}分</
p
>
<
table
>
<
thead
>
<
tr
>
<
th
>ID</
th
>
<
th
>姓名</
th
>
<
th
>分数</
th
>
<
th
>操作</
th
>
</
tr
>
</
thead
>
  
<
tbody
ms-each-el
=
"array"
>
<
tr
>
<
td
>{{el.id}}</
td
>
<
td
>{{el.name}}</
td
>
<
td
>{{el.score}}</
td
>
<
td
align
=
"center"
><
a
ms-click
=
"$remove"
href
=
"javascript:void(0)"
>移除</
a
></
td
>
</
tr
>
</
tbody
>
</
table
>
<
textarea
ms-value
=
"JSON.stringify(array.$model)"
style
=
"width:90%;height:220px;"
></
textarea
>
</
div
>
样式随便弄弄:

.grid
table{
border
:
1px
solid
#000
;
width
:
500px
;
border-collapse
:
collapse
;
}
.grid
button{
width
:
400px
;
background
:orange;
}
.grid
table th, .grid table td{
border
:
1px
solid
#000
;
padding
:
2px
5px
;
}
从HTML结构来看,分为两部分,一个是用于输入数据,另一个是呈现所有数据,数据上方还有个小统计。输入数据部分有三个输入项,我们对分数中进行校验,只保证其是数字就行了,目的是为了相加,因为input的value属性总为一个字符串类型。下方有个按钮,用于提交。呈现区为一个table,所有MVVM框架都支持数组循环输出,我的与angular走得很近。在循环区域,里面还内置一个$remove方法,用于删除监控数组中的某一个元素,这个比knockout人性化多了。下面是JS部分,你是看不到一句操作DOM的代码。

//如果大家对avalon不熟悉,可以参看这篇入门教程
 http://www.cnblogs.com/rubylouvre/p/3181291.html[/code]
avalon.ready(
function
()
{
var
model
= avalon.define(
'grid'
,
function
(vm)
{
vm.id
=
""
vm.name
=
""
vm.score
= 0
vm.total
= 0
vm.add
=
function
()
{
   
if
(vm.id
&& vm.name ){
   
vm.array.push({
  
id:vm.id,
  
name:vm.name,
  
score:vm.score
   
})
   
}
}
vm.array
= []
   
});
model.$watch(
"score"
,
function
(a)
{
var
a
= Number(a) || 0
a
= a > 100 ?  100 : a < 0 ? 0 : a
//强制转换为0~100间
model.score
= a
})
model.array.$watch(
"length"
,
function
()
{
var
a
= 0
model.array.forEach(
function
(el)
{
a
+= el.score
//求得总数
})
model.total
= a;
model.id
=
""
model.name
=
""
model.score
= 0
})
model.array
= [
{id:
"d1"
,name: 
"李世民"
,score: 67},
{id:
"d2"
,name: 
"赢政"
,score: 90}
]
avalon.scan();
});
我们在define方法中定义了VM所有用到的数据,什么id, name, score, array, 还有需要绑到视图中的add方法。数据校验或数据变动时需要做的操作,我们是用$watch实现,它们被安排到define方法外,这是一个好主意。然后,就没有然后了!这就是MVVM的神奇之处,因为我们在视图中使用了{{}}, ms-click已经指明了它们的行为。因此当数据变动时,框架自然明白自己该什么做。

add

共2条------------------合计157分
ID姓名分数操作
d1李世民67移除
d2赢政90移除
目前我与5群的一些人已经将avalon应用于公司的生产环境,反应还是不错。虽然目前还不时冒出一些怪异的BUG,但难度不至于影响我们的进度,基本上半天就能修,比如说IE9-10的option标签的value问题,firefox 全系列下,未插入DOM树的元素的display样式取值问题,这是jQuery也没报到的新东西。有的话,我在做mass Framework时已经遇到过了。MVVM是一个全新的领域,要求对用户全面隐藏DOM操作,并将整个DOM树作为一个动态模板或数个复用的子模板,另外,DOM树其实也被我框架看作为一个Ioc容器的配置文件。如此种种,遭遇新的问题在所难免,但只要方向是对的,这就是康庄大道。虽然它与jQuery走的是一条截然不同的路,但明显优于jQuery。jQuery与DOM存在强依赖,导致维护成本奇高。这正是西方继jQuery后,又孜孜不倦发明backbone,canjs, knockout, emberjs, angular的原因。现在国内的技术步伐普通比外国慢两三年,现在前端MVVM已经在外国非常盛行,希望国人不要再落后太多了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: