轻量级mvvm Web开发框架 postby:http://zhutty.cnblogs.com
今天特别郁闷,怎么说呢,之前一直就用angular,然后这两天用的是avalon这东西,反正,一开始没时间去玩它,第一个任务就是封装个jq插件,实现一个小功能。反正呢,就是越写越郁闷。用过angular的同学在去用jq应该都会有这种感觉吧。多此一举,费事。主要是,jq去一个一个操作dom树,把我搞郁闷了,最后,插件好了,但在一个地方用了好几次,这下好了,出问题了。问题像是这样的,晒出来供大家吐槽。
$.fn.PlaginName = function($){
//这个插件实现的内容就是点击一个元素,然后发出一个ajax请求
}
/******我下面是在require中这样用的****/
$('.class1').PlaginName();
$('.class2').PlaginName();
$('.class3').PlaginName();
大概就是这样吧,反正呢,结果就是,我三个地方随便一个地方点击事件,都会出发插件里的响应函数,导致请求了三次。这直接导致了我心塞了一下午。。。。。。。
最后决定,放弃这个方案,既然都用了mvvm,干嘛还用这个低效率的jq呢。不过,有上述解决方案的童鞋,可以吐槽在评论。
进入正题,其实jq已经很普及了,后来人们发现,项目大了,管理维护这一堆散散的代码,实在是蛋蛋的忧伤。于是应用了后端开发mvc思想到前端开发中。最先的前端mvc框架就是backbone了。不过,我只看了看它,听网友们的神吐槽说backbone使得代码量不降反增。我看了backbone写的那个todo list那个例子,确实有点繁琐。后来,借鉴了微软的wpf,于是出现了好多mvvm框架了,就是视图和模型双向绑定。最出名的就是angular了,全能神啊,有了它,你可以把jq丢垃圾桶了。不过,程序猿们有点不开心了,不为别的,就说性能。。。。。。然后挑刺,嫌angular太肥了,然后,各种剔除,改装。然后就有了avalon了,不过,这个东东,在我天朝还是有好些人在用的:好入手,快速开发。
avalon官方地址:http://avalonjs.github.io/#home.html
看看官方API:
静态方法与属性
- mix(a,b), 相当于jQuery.extend
- vmodels, 用于放置生成的ViewModel
- log(s), 打印日志
- error(s),抛出异常
- ui, 用于放置组件
- noop, 一个空函数
- ready(fn), domReady,将回调延迟到DOM树后才执行
- oneObject(str|array, val?), 如果传入一个字符串则将它以逗号转换为一个字符串数组,否则一定要传字符串数组,第二个参数可选,为生成的对象的值。此方法是用于生成一个键名不一样,但键值都一样的对象。如{a:1,b:1,c:1,d:1}
- type(obj), 返回传参的数据类型,值可能为array, date, object, json, number,string, null, undefined
- isWindow(obj), 判定是否为window对象
- isPlainObject(obj), 判定是否是一个朴素的javascript对象(Object),不是DOM对象,不是BOM对象,不是自定义类的实例。
- slice(obj, start?, end?), 用于转换一个类数组对象为一个纯数组,后面两个为索引值,可以只取原对象的一部分元素。
- range(start, end, step),生成一个整数数组,功能与underscorejs或python的同名函数一致。
- bind(el, type, fn, phase),绑定事件,返回一个回调给你行卸载
- unbind(el, type, fn, phase),卸载事件
- each,功能同jQuery.each, 都是索引值或键名在前,值或元素在后
- avalon.define(id?, factory),定义一个ViewModel
- scan(element?, ViewModel?),开始扫描DOM树,抽取绑定。
- define(id?, deps?, factory),一个全局方法,用于定义AMD规范的JS模块
- require( deps, callback),一个全局方法,用于加载JS模块
- css( node, name, value?),如果只有两个参数,读取元素的某个样式,三个参数时,设置元素某个样式
- nextTick(fn),延迟执行某个函数,类似于setTimeout(fn, 0)
- contains(a, b),判定A元素包含B元素
- parseHTML(str),将一段字符串转换为文档碎片
- innerHTML(node, str),对节点node进行innerHTML操作,在旧式IE下,head, table, td, tr, th等元素的innerHTML是只读,这个方法进行了兼容处理。
- clearHTML(node),清空元素的所有子节点。
avalon.Array
- remove(array, el),移除某个元素,成功返回true,失败返回false
- removeAt(array, index),移除某个位置上的元素,成功返回true,失败返回false
- ensure(array, el),只有数组不存在此元素时才添加它
另,avalon对Array.isArray上做了兼容处理,IE6也可以使用此方法
avalon.filters
各种过滤器
- uppercase(str),全部大写
- lowercase(str),全部小写
- truncate(str, length, truncation),length,新字符串长度,truncation,新字符串的结尾的字段
- camelize(str),驼峰化
- escape(str),将字符串经过 html 转义得到适合在页面中显示的内容, 例如替换 < 为 <
- currency(str,symbol),货币处理,默认第2个参数为¥
- number(str,decimals, dec_point, thousands_sep),数字格式化。date(str, format),对日期进行格式化。str可以是毫秒数也可以是日期对象,format是诸如“YYYY MM dd HH:mm:ss”的格式
- 必需。要格式化的数字。
- decimals 可选,规定多少个小数位。
- dec_point 可选,规定用作小数点的字符串(默认为 . )。
- thousands_sep 可选,规定用作千位分隔符的字符串(默认为 "," )。如果设置了该参数,那么所有其他参数都是必需的。
-
'yyyy': 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) 'yy': 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) 'y': 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) 'MMMM': Month in year (January-December) 'MMM': Month in year (Jan-Dec) 'MM': Month in year, padded (01-12) 'M': Month in year (1-12) 'dd': Day in month, padded (01-31) 'd': Day in month (1-31) 'EEEE': Day in Week,(Sunday-Saturday) 'EEE': Day in Week, (Sun-Sat) 'HH': Hour in day, padded (00-23) 'H': Hour in day (0-23) 'hh': Hour in am/pm, padded (01-12) 'h': Hour in am/pm, (1-12) 'mm': Minute in hour, padded (00-59) 'm': Minute in hour (0-59) 'ss': Second in minute, padded (00-59) 's': Second in minute (0-59) 'a': am/pm marker 'Z': 4 digit (+sign) representation of the timezone offset (-1200-+1200)
-
format string can also be one of the following predefined localizable formats: 'medium': equivalent to 'MMM d, y h:mm:ss a' for en_US locale (e.g. Sep 3, 2010 12:05:08 pm) 'short': equivalent to 'M/d/yy h:mm a' for en_US locale (e.g. 9/3/10 12:05 pm) 'fullDate': equivalent to 'EEEE, MMMM d,y' for en_US locale (e.g. Friday, September 3, 2010) 'longDate': equivalent to 'MMMM d, y' for en_US locale (e.g. September 3, 2010 'mediumDate': equivalent to 'MMM d, y' for en_US locale (e.g. Sep 3, 2010) 'shortDate': equivalent to 'M/d/yy' for en_US locale (e.g. 9/3/10) 'mediumTime': equivalent to 'h:mm:ss a' for en_US locale (e.g. 12:05:08 pm) 'shortTime': equivalent to 'h:mm a' for en_US locale (e.g. 12:05 pm)
-
avalon.fn
要求传入一个元素节点或文档对象或window,你可以通过$().element, $()[0]再次访问到你传入的东西。它有以下原型方法。
- hasClass(cls),判定有没有此类名
- addClass(cls),只有元素不存在时才添加此类名(可同时添加多个)
- remvoeClass(cls),移除多个类名
- toggleClass(cls, state?),切换多个类名,如果第2个参数为布尔,则根据它强行添加或删除类名
- attr(name,value?), 读写特性(此方法非常弱,直接使用setAttribute, getAttribute实现,没有做任何兼容性处理)
- data(name, value?), 读写数据,使用HTML5的data-*特性实现。它会parse一下,让数据更为实用,思路同jQuery,如果一个传参也没有,将元素的data-*属性组成一个对象返回
- removeData(name), 移除数据
- css(name,value?),读写样式,这个兼容性做得很好,因为长达一百行,连HTML5的私有前缀都能你补上。
- width(val?), 读写宽度,注意对隐藏元素没有处理。
- height(val?), 读写高度,注意对隐藏元素没有处理。
- bind(type, fn, phase),绑定事件,这个没有做链式操作,目的是为了返回回调给你卸载。
- unbind(type,fn, phase),卸载事件。
- val,读取表单元素的value值,功能同jQuery。
- offset,取得元素在文档中的坐标,功能只实现了jQuery的一半,只能读不能写。
- scrollLeft,取得水平滚动条的位置。
- scrollTop,取得垂直滚动条的位置。
各种绑定
- ms-html="str", 设置innerHTML,会清空此元素下的所有节点
- ms-class="className:boolean", 切换类名
- ms-hover="className", 移上去时添加这类名,移出去掉。
- ms-active="className", 获得焦点添加这类名,失去焦点去掉。
- ms-visible="boolean", 操作元素的style.display实现显示隐藏
- ms-if="boolean", 决定是将此元素放出到DOM树还是移出
- ms-each-el?="array", el用于下面的引用。在它的作用范围,你还可以访问$index得到其索引值,$first判定是否第一个元素,$last是否最后一个,$remove为一个方法,你执行它就会从数组中删除它,并将它作用的那一片元素都移出DOM树。
- ms-duplex="property",只能用于表单元素,与ViewModel中的某些字段双向绑定,它会偷偷绑定一些事件进行同步。
- ms-controller="ViewModelName",指定一个ViewModel的作用范围
- ms-important="ViewModelName",指定这个区域只能由这个ViewModel来渲染
- ms-skip,不对此元素及后代进行扫描绑定,保证原样输出。
- ms-on-type="callback",绑定一个事件,type为事件名,如ms-on-click="tick"。什么ms-click, ms-focus, ms-keyup, ms-keydown都是由它衍生出来的。
- ms-click="callback",ms-keypress="callback",ms-keydown="callback", ms-keyup="callback",ms-mousedown="callback"……等常用事件都做了一个快捷方式。
- ms-href, ms-alt, ms-src, ms-title,ms-value这些绑定的属性如果不带有{{ }},则以其他绑定一样,直接eval属性值, 然后设置href, alt, src, title, value等属性,如果带有着{{ }},那么整个将变成插值表达式,返回一个文本,然后赋给相关属性。
- ms-css-xxx="val",规则同ms-href,不同的是, 它赋值是使用css方法,即avalon(element).css(xxx, val)
- ms-disabled,ms-readyonly,ms-selected,ms-checked等布尔属性,根据属性值的情况决定添加与移除
- ms-enabled="boolean",与ms-disabled相反。
- {{ expr }}, 插值表达式,与angular相同,可以使用“|filter(args1, args2)”的形式添加多个过滤器。
- {{ expr|html }}, 相当于ms-html,但不会影响它的兄弟节点。
- ms-widget="name, id?, opts?",添加一个组件。
- uiName,必选,一定要全部字母小写,表示组件的类型。
- id 可选 这表示新生成的VM的$id,方便我们从avalon.vmodels[id]中获取它操作它。 如果它等于$,那么表示它是随机生成,与不写这个效果一样,框架会在uiName加上时间截,生成随机ID。
- optName 可选, 配置对象的名字。指在已有的VM中定义一个对象(最好指定它为不可监控的外),作为配置的一部分(因为每个UI都有它的默认配置对象,并且我们也可以用data- uiName? -xxx来做更个性化的处理 )。如果不指optName默认与uiName同名。 框架总是找离它(定义ms-widget的那个元素节点)最近的那个VM来取这个配置项。
ViewModel
- 与angular的要求一致,$开头的为框架所保留,由于在IE6-8中然后VBS实现,无法区分大小写,不要同一个ViewModel定义两个近似的方法名。
- $id为ViewModle的名字
- $events为一个对象,用于保存$watch方法的回调
- $watch(prop, callback),ViewModel只能通知它的视图进行更新,不能通知他在ViewModel的其他属性,对于监控属性,我们可能通过这方法实现兄弟间的通信。
- $unwatch(prop,callback?),停止通知
- $model,对应ViewModel的普通javascript对象形式(早期的版本,它是叫做$json)
- 以$开头的属性,框架都不会将它转换为监控属性
- 放在$skipArray中的属性名,也不会转换为监控属性
- 一个包含get与set的对象被认为是一个计算属性。
以上这部分是官网的api, 接下来,看看如何使用它。
待续。。。。。