Javascript 的分层概念
description
Transcript of Javascript 的分层概念
JavascriptJavascript 的分层概念的分层概念
曹刘阳 (阿当)
原生原生 javascriptjavascript
目录
底层、组件层和应用层底层、组件层和应用层
YUI2YUI2
JQueryJQuery
YUI3YUI3
原生原生 javascriptjavascript
变量冲突:变量冲突:
<input type="button" value="click me" id="btn" />
<script type="text/javascript">
// 功能 A
var a = 1,btn = document.getElementById("btn");
btn.onclick = function(){
a++;
alert(a); // 101 、 102 、 103…
}
</script>
...
<script type="text/javascript">
// 功能 B
var a = 100; // 在此处被重新赋值
</script>
变量暴露在 window 作用域下,多人合作 \ 多个功能间互相干扰。
<ul id="list">
<li id="firstItem">111</li>
<li>222</li>
<li>333</li>
</ul>
<script type="text/javascript">
var list = document.getElementById("list") ,
firstItem = document.getElementById("firstItem");
alert(firstItem.nextSibling.innerHTML); // IE : 222 firefox : undefined
alert(list.childNodes.length); // IE : 3 firefox : 7
</script>
DOMDOM 相关相关 -1-1 ::
<style>#test{width:300px;height:300px;background:blue;}</style><body><div id="test"></div><script type="text/javascript">var test = document.getElementById("test");if(document.all){
test.style.filter = ‘alpha(opacity=20)’; // IE}else{
test.style.opacity = 0.2; // firefox}</script>
DOMDOM 相关相关 -2-2 ::
不同浏览器,对 DOM 的解析不同
<input type="button" value="click me" id="btn" />
<span id="span">hello world</span>
<script type="text/javascript">
document.getElementById("btn").onclick = function(e){
e = window.event || e;
var el = e.srcElement || e.target;
alert(el.tagName);
}
document.getElementById("span").onclick = function(e){
e = window.event || e;
var el = e.srcElement || e.target;
alert(el.tagName);
}
</script>
EventEvent 相关相关 -1-1 ::
<input type="button" value="click me" id="btn" />
<script type="text/javascript">
var btn = document.getElementById("btn");
if(document.all){ // IE
btn.attachEvent("onclick",function(){
alert("hello world");
});
} else { // firefox
btn.addEventListener("click",function(){
alert("hello world");
},false);
}
</script>
EventEvent 相关相关 -2-2 ::
不同浏览器,对 Event 的解析不同
// 设置 cookie
document.cookie = "name=adang; expires= Mon, 04 Oct 2010 02:40:14 GMT; path=/";
document.cookie = "sex=male; expires= Mon, 04 Oct 2010 02:40:14 GMT; path=/";
document.cookie = "blog=http://www.adanghome.com; expires= Mon, 04 Oct 2010 02:40:14 GMT; path=/";
/* 读取 cookie
** 此时 cookie 里的值为 "name=adang; sex=male; blog=http://www.adanghome.com"
*/
var cookieStr = document.cookie;
// 对字符进行操作,取出 name 对应的值
var name = cookieStr.split("name")[1].split(";")[0].split("=")[1];
alert(name);
其它操作:其它操作:
原生 javascript 接口太笨拙
原生 javascript 写程序就像汽车行驶在一条凹凸不平的小路上。
底层、组件层和应用层底层、组件层和应用层
控制全局作用域的变量数量:控制全局作用域的变量数量:
<input type="button" value="click me" id="btn" />
<script type="text/javascript">
(function(){
var a = 1,btn = document.getElementById("btn");
btn.onclick = function(){
a++;
alert(a);
}
})();
</script>
...
<script type="text/javascript">
(function(){
var a = 100;
})();
</script>
问题一:匿名函数间无法通信
问题二:如果匿名函数内容很长 ,函数内部还是有冲突隐患
命名空间命名空间
<script type="text/javascript">
var GLOBAL = {};
GLOBAL.namespace = function(str){
var arr = str.split("."),o = GLOBAL;
for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) {
o[arr[i]]=o[arr[i]] || {};
o=o[arr[i]];
}
}
</script>
<script type="text/javascript">
(function(){
GLOBAL.namespace("A"); GLOBAL.A.a=1;
var btn = document.getElementById("btn");
btn.onclick = function(){
GLOBAL.A.a++;
alert(GLOBAL.A.a);
}
GLOBAL.namespace("B"); GLOBAL.B.a = 100;
})();
</script>
...
<script type="text/javascript">
(function(){
var a = 100;
alert(a);
alert(GLOBAL.A.a);
})();
</script>
封装封装 DOMDOM 的接口的接口
<script type="text/javascript">
function getNextNode(node){
if(ie){
…
} else {
…
}
};
function setOpacity (node,opacityValue){
if(ie){
…
} else {
…
}
}
</script>
封装封装 EventEvent 的接口的接口
<script type="text/javascript">
function getEventTarget(e){
if(ie){
…
} else {
…
}
};
function on (node,eventType,handler){
if(ie){
…
} else {
…
}
}
</script>
将函数归到相应的命名空间下:将函数归到相应的命名空间下:
<script type="text/javascript">
var GLOBAL = {};
GLOBAL.namespace = function(str){ … };
… // GLOBAL.extend 、 GLOBAL.merge
GLOBAL.namespace(“Dom”);
GLOBAL.Dom.getNextSibling = function(){ … }
GLOBAL.Dom.setOpacity = function(){ … }
… // GLOBAL.Dom.getPrevSibling 、 GLOBAL.Dom.getStyle
GLOBAL.namespace(“Event”);
GLOBAL.Event.getEventTarget = function(){ … }
GLOBAL.Event.on = function(){ … }
… // GLOBAL.Event. stopPropagation 、 GLOBAL.Event.getXY
</script>
将 DOM 、 Event 相关的操作进行封装,另外扩展一些原生javascript 语言层面不提供的接口,组成新的底层。
底层替我们铲平了路面的凸起(浏览器差异),填补了路面的凹陷(补充 javascript 语言的底层方法)
封装封装 cookiecookie 的接口的接口
<script type="text/javascript">
var cookie = {
set : function(){
…
},
read : function(){
…
},
del : function(){
}
};
</script>
将函数归到相应的命名空间下:将函数归到相应的命名空间下:
<script type="text/javascript">
GLOBAL.namespace(“Cookie”);
GLOBAL.Cookie = {
set : function(){ …}
read : function(){ … }
del : function(){ … }
}
… // GLOBAL.Ajax 、 GLOBAL.Drag 、 GLOBAL.Resize…
</script>
将常见功能封装成组件,组件将内部实现细节透明,提供简单易用的接口。
组件层替我们在路面铺上沥青,将普通小路变成高速公路。
应用层应用层::和页面具体需求相关,调用底层的底层接口和组和页面具体需求相关,调用底层的底层接口和组件层的组件,依赖底层和组件层。件层的组件,依赖底层和组件层。
组件层组件层::调用底层提供的接口,封装常用组件,依赖底层。调用底层提供的接口,封装常用组件,依赖底层。和具体功能有关,但和页面需求无关。为应用层提供组件(组和具体功能有关,但和页面需求无关。为应用层提供组件(组件提供组件的接口)。例如件提供组件的接口)。例如DragDrag 、、 CookieCookie 、、 AjaxAjax 、、 ResizeResize 、、 TabTab 、、 TreeTree 。。
底层底层 : :封装封装 DOMDOM 、、 EventEvent 在各浏览器下的区别,提供在各浏览器下的区别,提供统一的接口统一的接口 ;; 扩展扩展 javascriptjavascript 语言,提供全局性的方法。和具语言,提供全局性的方法。和具体功能无关,只为组件层和应用层提供底层接口。例如体功能无关,只为组件层和应用层提供底层接口。例如getNextSiblinggetNextSibling ()、()、 getEventTargetgetEventTarget ()、()、 namespacenamespace (()、)、 trimtrim ()、()、 isArray()isArray() 。。
典型的引用方法:典型的引用方法:
<html>
<head>
<title> 阿当制作 </title>
</head>
<body>
<script type = “ text/javascript ” src = “ base.js ”></script> <!-- 底层 -->
<script type = “ text/javascript ” src = “ ajax.js ”></script> <!– 组件层 -->
<script type = “ text/javascript ” src = “ tab.js ”></script> <!-- 组件层 -->
<script type = “ text/javascript ”> <!-- 应用层 -->
(function(){
// your code here
})();
</script>
</body>
</html>
应用层应用层:: 1) 1) 避免多人合作的冲突避免多人合作的冲突 ;; 2) 2) 组件间的依赖关系处理组件间的依赖关系处理 ; ;
组件层组件层:: 1) 1) 尽可能丰富的组件尽可能丰富的组件 ;; 2) 2) 易用性易用性 ;; 3) 3) 可重用性。可重用性。
底层底层 : : 1) 1) 跨浏览器兼容跨浏览器兼容 ,, 屏蔽尽可能多的浏览器差异屏蔽尽可能多的浏览器差异 ;; 2) 2) 补充完善补充完善 javascriptjavascript 语言本身的不足语言本身的不足 ;;
3) 3) 精简。精简。
底层 底层 + + 组件层 组件层 = = 框架框架
框架可以帮助我们将精力集中在应用层的逻辑处理上,框架可以帮助我们将精力集中在应用层的逻辑处理上,例如设计类、接口、设计模式,而不是将精力放在频例如设计类、接口、设计模式,而不是将精力放在频繁的底层操作上。繁的底层操作上。
例:例: http://www.adanghome.com/js_demo/1/http://www.adanghome.com/js_demo/1/
开发框架的难点:代码品质、组件的丰富程度、兼容开发框架的难点:代码品质、组件的丰富程度、兼容性、易用性、可复用性…性、易用性、可复用性…
我们有大量开源框架可以选择:我们有大量开源框架可以选择: jQueryjQuery 、、 YUIYUI 、 、DojoDojo 、 、 PrototypePrototype 、、 mootool…mootool…
YUI2YUI2
官方网址:官方网址: http://developer.yahoo.com/yui/2/http://developer.yahoo.com/yui/2/
jQueryjQuery
官方网址:官方网址: http://www.jquery.comhttp://www.jquery.com
““ 小”与“强”的平衡:小”与“强”的平衡:
YUI2YUI2 将文件分成粒度非常小,靠将文件分成粒度非常小,靠 loaderloader 机制按需加载,达到机制按需加载,达到“小”和“强”的平衡,扩展性好“小”和“强”的平衡,扩展性好 ;;
jQueryjQuery 靠作者强大的个人能力,将靠作者强大的个人能力,将 jsjs 编程发挥到极致,达到编程发挥到极致,达到“小”和“强”的平衡,扩展性差。“小”和“强”的平衡,扩展性差。
处理依赖关系:处理依赖关系:
YUI2YUI2 通过通过 loaderloader 动态加载样式和脚本,智能地完成依赖关系的动态加载样式和脚本,智能地完成依赖关系的处理,调用简单,不易出错处理,调用简单,不易出错 ;;
jQueryjQuery 使用传统方式,手动添加样式和脚本,易出错。使用传统方式,手动添加样式和脚本,易出错。
第三方组件:第三方组件:
YUI2YUI2 所有组件都是官方提供,第三方组件少,但代码品质高。所有组件都是官方提供,第三方组件少,但代码品质高。
jQueryjQuery 有大量第三方组件,但代码品质参差不齐。有大量第三方组件,但代码品质参差不齐。
实际工作情况:实际工作情况:
应用层应用层::调用下面三层调用下面三层自定义组件层自定义组件层::我们提供,定制型我们提供,定制型
框架组件层框架组件层::框架提供,通用型框架提供,通用型底层 底层 ::框架提供,通用型框架提供,通用型
存在的问题:存在的问题:11 )如何处理多人合作的问题)如何处理多人合作的问题 ;;22 )自定义类的格式。)自定义类的格式。
类库?框架?类库?框架?
类库提供预编写好的类,隐藏底层操作,简化开发。帮助工程类库提供预编写好的类,隐藏底层操作,简化开发。帮助工程师将精力集中在应用层。师将精力集中在应用层。
框架提供整套解决方案,除类库之外,还包括应用层的格式和框架提供整套解决方案,除类库之外,还包括应用层的格式和自定义组件的格式。进一步帮助工程师将精力从“格式”中解自定义组件的格式。进一步帮助工程师将精力从“格式”中解放出来,专注于“逻辑”处理。放出来,专注于“逻辑”处理。
YUI3YUI3
官方网址:官方网址: http://developer.yahoo.com/http://developer.yahoo.com/yui/3yui/3
widgetwidget
init()init()destroy()destroy()render(){render(){
renderUI();renderUI();bindUI();bindUI();syncUI();syncUI();
}}MyWidget.HTML_PARSERMyWidget.HTML_PARSER = { }
例:例: http://www.adanghome.com/js_demo/2/http://www.adanghome.com/js_demo/2/
YUI3YUI3 带来的分层:带来的分层:
应用层应用层::如有自定义类,继承抽象类如有自定义类,继承抽象类自定义组件层自定义组件层::我们提供,继承自抽象类我们提供,继承自抽象类
框架组件层框架组件层::框架提供,继承自抽象类框架提供,继承自抽象类抽象类层抽象类层::框架提供框架提供 ,, 统一自定义类的格式统一自定义类的格式底层底层::框架提供框架提供