新一代轻量级高性能移动web框架,由腾讯前端团队
AlloyTeam
经项目实践积累沉淀而成。为拥抱移动互联网全新设计,专注为移动web项目,整个框架压缩后只有36K
新的移动平台,给web带来更多的机会,同时也带来更多的挑战。原PC端的各种浏览器兼容,已经升级为多平台多终端多版本多浏览器的复杂问题。为了解决这个问题,各种移动框架应运而生,但是为了解决问题而使整个库的体积庞大,最终在兼容和性能的权衡上没有取得平衡。JM在设计上更看重性能
,所以代码量上力求精简,同时能够处理大部分的移动web兼容问题。或许你发现JM并没有过多地为帮你做什么事情,但我们却为你避开了很多移动上的坑。
下面我们尝试使用JM来写一个HelloWorld程序,通过这个小Demo,你可以对JM有个概括的了解。
主要html
<button id="myButton" class="btn btn-primary btn-block" >
<span class="btn_text">Hello World</span>
</button>
<div class="word">
<div id="word1">Hello World !</div>
<h2 id="word2" >by Tencent AlloyTeam</h2>
</div>
主要js
var $E = JM.event;
var $D = JM.dom;
var btn = $D.id('myButton');
var word1 = $D.id('word1');
var word2 = $D.id('word2');
$E.on(btn,'click',function(){
//设置动画基本参数,并且每个动画间隔为1.5秒
J.Animation({
selector:'#word1',
duration:1500,
use3d:true
}).setStyle({ //向右运动了40%,并且color变成蓝色
'top':'60px',
'opacity':'1'
}).transit(function(){
this.setDuration(600);
this.scale(2).setStyle({
'top': '40px',
'opacity':'0'
}).transit(function(){
word1.style.cssText = ""; //清空dom的style,让动画回归起初状态
});
});
J.Animation({
selector:'#word2',
duration: 1500,
use3d : true
}).setStyle({
'top':'140px',
'opacity':'1'
}).transit(function(){
this.setDuration(800);
this.scale(2).setStyle({
'top': '150px',
'opacity':'0'
}).transit(function(){
word2.style.cssText = "";
});
});
});
代码解析
示例程序的button样式额外地使用了JMUI
的button样式,不使用也没有影响,样式可以你写你喜欢的。我们来看看js代码部分,$D
和$E
是引用jm的模块名,这样再代码使用中更加简洁而已,你完全也可以var btn = JM.dom.id('#word1');
。代码中展示了JM三个模块的使用:Dom节点选择器,事实处理机制,动画模块。
JM除了提供常规的选择器外JM.dom.$(selectorText)
,还提供专门的选择id选择器JM.dom.$(id)
,我们也建议尽量使用id选择器,因为在效率上id选择器是最快的。在事件处理上JM.event.on(obj, evtType, handler)
,obj为绑定的dom节点,evtType为事件类型,hadler的事件处理函数,obj和handler都可以输入数组,我们支持多对象多事件同时处理处理。还有些常规的off,one,fire等方法外,还对swip,hold,toch等移动专属事件方法,详细情况可以参考event模块。
事件处理的代码里面是JM.Animation
内容。有两个段动画代码,我们看第一段就可以了。传给Animation的是一些基本参数,其中use3d
来开启这段动画是否使用GPU的3D动画加速(注意这不是银弹,不是所有动画都必须加上),setStyle
方法顾名思义设置要修改的样式,transit
方法就是把我们setStyle
修改的样式使用css3的transiton的动画形式展示,transit
方法只接受一个FinshFunc参数,动画执行后就会执行FinshFunc。通过在FinshFunc函数里在写动画函数,就形成动画回调了。在最后的transit
方法回调中,我们把dom的style属性取消掉,这样进行动画就会回归源点。
动画模块,JM的动画实现全部由CSS3实现,有以下几个特征
核心代码
runBtn.onclick = function(){
$D.setStyle(runBtn,"display","none");
rect.style.cssText = "";
//设置动画基本参数,并且每个动画间隔为1秒
J.Animation({
selector:"#demo1_rect", //要操作的dom的selector
duration:1000,
use3d:true
}).setStyle({ //向右运动了60%,并且color变成蓝色
"left":"60%",
"background":"blue"
}).transit(function(){
this.scale(.5).setStyle({
'background':"red"
}).transit(function(){
this.rotate(180).setStyle({
opacity:0
}).transit(function(){
this.toOrigin().setStyle({
"opacity":1,
"background":"green"
}).transit(function(){
$D.setStyle(runBtn,"display","block");
});
});
});
});
}
J.Animation是这个模块的命名模块,传入一个options的obj来设置动画的基本参数。然后在函数尾部使用setStyle
进行回调,setStyle
是用于设置动画改变的状态。再在函数尾部调用transit
方法表示以CSS3的transition方式进行启动动画。我们依旧在transit
里面传入匿名函数,表示一段动画结束后,进行回调函数callback,这样我们就不断进行链式调用
和callback回调来完成一段动画。
大体上动画函数都很好理解,不做过多解析,我们使用链式js的方式来编辑CSS3动画,CSS3的动画参数都可以自个设置,并且动画结束后可自行销毁,不会冗余页面代码样式。
在web上播放声音一直体验都不是很好,包括下载声源需要加载时间,而且各种的声音播放方式兼容性差等等。JM的额外模块audio是就是处理web上声音的模块。因为不是所有的web页面都需要声音,所以我们建议需要播放声音的时候才加载这个模块。在HTML5
诞生到来,让web在多媒体领域上不区于flash,原生的控件,让我们的页面播放页面更加简单。但是并不是真正的简单,问题依旧是浏览器间的问题,或者是各种终端版本的问题,兼容性依旧是个核心问题。我们audio模块就是为了解决播放声音的兼容性及操作的一致性而生,让我们的声音在web上,在真正意义上的简单起来。
JM的一些核心方法,为所有模块所共用。例如JM的命名方式namespace
,类封装Class
,继承extend
,操作Listfilter``map``some
等一系列继承函数。
示例代码
JM.$package("MUI",function(J){
// JM的命名空间
});
//JM的类继承方式
var AnimateTab = J.Class({extend:MUI.Tab},{
init:function(options){
//do something
},
_handleEvent:function(e){
//do something
},
bindHandlers:function(){
//do something
}
});
本可简单简单地划分到utils模块,但是在移动web上我们检测的不单单是浏览器及其版本后,后继拓展还有,终端平台及其版本,所以我们单独地划分出一个模块出来(其实最终还是会合到一个js里面)。
//对应的值是版本号,如果不是这个浏览器则版本号为0
if(J.browser.plugins.flash>=9){
}
if(J.browser.ie){
}
if(J.browser.chrome >= 30){
}
if(J.adobeAir){
}
非常简单的cookie种植和移除,直接粘贴源码吧
J.$package(function(J){
var domainPrefix = window.location.host;
var cookie = {
set : function(name, value, domain, path, hour) {
if (hour) {
var today = new Date();
var expire = new Date();
expire.setTime(today.getTime() + 3600000 * hour);
}
window.document.cookie = name + "=" + value + "; " + (hour ? ("expires=" + expire.toGMTString() + "; ") : "") + (path ? ("path=" + path + "; ") : "path=/; ") + (domain ? ("domain=" + domain + ";") : ("domain=" + domainPrefix + ";"));
return true;
},
get : function(name) {
var r = new RegExp("(?:^|;+|\\s+)" + name + "=([^;]*)");
var m = window.document.cookie.match(r);
return (!m ? "" : m[1]);
},
remove : function(name, domain, path) {
window.document.cookie = name + "=; expires=Mon, 26 Jul 1997 05:00:00 GMT; " + (path ? ("path=" + path + "; ") : "path=/; ") + (domain ? ("domain=" + domain + ";") : ("domain=" + domainPrefix + ";"));
}
};
J.cookie = cookie;
});
HTML的dom操作模块。包括选择器,选取样式,修改样式切换Class等方法。虽然跟著名的jquery对比会逊色一筹,但是基本的功能都能满足,最重要的是jquery有100多K,我们才30多K,我们把最实际常用的Dom操作抽离处理,减少库的代码量,在移动Web上带来更少的流量。
示例代码
var $D = J.dom;
var runBtn = $D.id('runBtn'),
runObj = $D.$('#demo_block .rect'),
stopBtn = $D.className('demaxiya');
runBtn.onclick = function(){
$D.toggleClass(runBtn,'active');
}
if($D.getStyle(runBtn,'background') == '#000'){
$D.remove(stopBtn);
}
除了比较常用的J.dom.$()
的选择器方式,我们还提供了J.dom.id()
和J.dom.tagName()
等的选择器方式,我们建议,可以的话尽量是用id选择器,因为这是效率最高的。我们没有像Jquery那样吧选择到的Dom元素包装成一个Jquery对象,我们选择到的是原生的Dom元素,方式也是传入Dom和参数。It's simple,but it do well。
insertBefore
除了平常的支持IE等浏览器兼容外,最重要的是支持移动端的touch,swip等手势事件及transform等移动专有事件.PC端和移动端最大一个不同除了屏幕分辨率外,还有一个非常重要的就是事件不同。我们不但支持了这些事件,还自定义了手势事和提供了很多辅助方法,帮助开发者的实际开发应用,例如:getTouchPos``getDist
等。在移动web上坑最多的就是event处理的这一块,至少JM会让你少走很多弯路。
示例代码
var $E = J.event;
//动画事件结束后
$E.on(this.contentWrap,"webkitTransitionEnd",function(e){
// 自身销毁changed事件
$E.fire(self ,"changed" ,{
type:"changed",
currentIndex:self.currentIndex
});
});
var startEvt = isTouchDevice ? "touchstart" : "mousedown";
var moveEvt = isTouchDevice ? "touchmove" : "mousemove";
var endEvt = isTouchDevice ? "touchend" : "mouseup";
//touch事件的绑定
$E.on(document.body ,moveEvt ,_handleEvent);
$E.on(document.body ,endEvt ,_handleEvent);
注意,这里关于touch或swip事件的例子可以查看JMUI的控件,这样会更加清楚.
false
fire:function(obj,evtType){}
getActionTarget : function(event, level, property, parent){}
获取点击的事件源, 该事件源是有 cmd 属性的 默认从 event.target 往上找三层,找不到就返回null @param {Event} event
@param {Int}level 指定寻找的层次
@param {String} property 查找具有特定属性的target,默认为cmd
@param {HTMLElement} parent 指定查找结束点, 默认为document.body
@return {HTMLElement} | null
bindCommands : function(targetElement, eventName, commends, commendName){}
@example
bindCommands(cmds);
bindCommands(el, cmds);
bindCommands(el, 'click', cmds);
不多说,直接上源码
var date = function(date, formatString){
/*
* eg:formatString="YYYY-MM-DD hh:mm:ss";
*/
var o = {
"M+" : date.getMonth()+1, //month
"D+" : date.getDate(), //day
"h+" : date.getHours(), //hour
"m+" : date.getMinutes(), //minute
"s+" : date.getSeconds(), //second
"q+" : Math.floor((date.getMonth()+3)/3), //quarter
"S" : date.getMilliseconds() //millisecond
}
if(/(Y+)/.test(formatString)){
formatString = formatString.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
}
for(var k in o){
if(new RegExp("("+ k +")").test(formatString)){
formatString = formatString.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length));
}
}
return formatString;
};
http处理模块,一些处理urlparam方法和ajax方法。
示例代码
J.http.ajax({
url: 'http:www.xxx.com/getSomething'
method : 'post',
timeout : 50000,
withCredentials : true, //是否跨域
async : true, //是否异步
onError : function(data){
alert(' ajax error : ' + data.msg);
},
onSuccess : function(data){
//do something ...
},
onTimeout : function(data){
//do something ...
}
});
平台检查模块跟browser模块一样,是检测模块,后继优化会把两者这合并。为兼容多终端多版本,平台检查是少不了。
示例代码
if(J.platform.android && J.platform.ieVersion > 4){
//....
}
if(platform.android){
}
//其他平台检查
//platform.android
//platform.iPhone
//platform.iPad
//platform.iPod
//platform.winPhone
//platform.IOS
//.touchDevice
提供了集中使用prefixe的场景,dom节点,css,js等。
J.prefix.dom == 'WebKit'
J.prefix.lowercase == 'moz'
J.prefix.css == '-ms'
J.prefix.js == 'webkit'
提供tmpl 轻量的模板函数。encodeHTML
和decodeHTML
常用字符编码解析函数和一些URL操作的辅助函数。
目前特效检测内容只用audio,fixed,flash和transition。
J.support = {
audio : {
m4a : 'maybe',
mp3 : 'maybe',
ogg : 'probably',
wav : 'probably'
}
fixed : true,
flash : ture,
transitionend : 'transititonend'
}
提供常用的辅助函数,还有提供一些移动上特色需要的辅助函数,例如hideUrlBar
隐藏url栏,preventScrolling
禁止滚动等。