Javascript应用实践开发指南
渐进增强
- 渐进增强是一种分层设计网页的方式,其焦点是强调内容,用户与易访问性。
- 将Javascript文件的引用置于页面末尾
Javascript语言的基本功能
- 修改html文档
- 与服务器通信
- 存储数据
创建备用方案
编写可靠的Javascript代码 注意思路
if(typeof window.localStorage is supported){
//use localStorage
}else{
//use normal cookies
}
函数
一个循环遍历family数组元素并用alert方法回显其信息的函数
function getFamilyName(){
var family=[
"Ann",
"Jane",
"Mary",
"Tim"
];
var peopleCount=family.length;
if(peopleCount>0){
for(var i=0;i<peopleCount.length;i++){
var person=family[i];
if(person=="Tim"){
alert(person+',it's me!');
}else{
alert(person);
}
}
}
}
getFamilyName();
匿名函数
匿名函数要比采用通常方式所定义的函数执行效率高,因为他们不需要被引用,可以立刻执行,这种函数只能使用一次,不能反复使用。
(function(){
})
();
回调函数
如果某个函数被传入另一个函数中作为参数,那么就变成了回调函数,它既可以是用户自定义的函数,也可以是javascript中既有的原生函数。匿名函数也能充当回调函数。
window.addEventListener("load",function(){
alert(0);
},false);
方法
当函数被封装在对象之中,它就是方法。尽管有时那种深层嵌套于对象之中的函数会带来性能隐忧,不过以方法的形式来封装代码,在任何编程语言中都是一种既面向对象又极易维护的代码组织方式。
var getInformation={
"name":function(){
alert('get the name');
},
"checkTim":function(){
alert('check for tim');
}
};
window.addEventListenner("load",getInformation.names,false);
window.addEventListenner("click",getInformation.checkTim,false);
事件
事件机制是用来处理用户反馈的,如果想要在页面中执行Javacsript代码,那么必须先触发某种类型的事件才行。
- onabort 图像加载被中断
- onblur 元素失去焦点
- onchange 用户改变域的内容
- onclick 鼠标点击某个对象
- ondblclick 鼠标双击某个对象
- onerror 当加载文档或图像时发生某个错误
- onfocus 元素获得焦点
- onkeydown 某个键盘的键被按下
- onkeypress 某个键盘的键被按下或按住
- onkeyup 某个键盘的键被松开
- onload 某个页面或图像被完成加载
- onmousedown 某个鼠标按键被按下
- onmousemove 鼠标被移动
- onmouseout 鼠标从某元素移开
- onmouseover 鼠标被移到某元素之上
- onmouseup 某个鼠标按键被松开
- onreset 重置按钮被点击
- onresize 窗口或框架被调整尺寸
- onselect 文本被选定
- onsubmit 提交按钮被点击
- onunload 用户退出页面
操作文档对象模型
- getElementById
- getElementsByTagName:该方法返回一种名为NodeList的DOM对象,它是一个节点集合,有了NodeList对象,还需检查其长度,可以确保该值在脚本的有效范围内。从NodeList中获取一个节点有两种方法:item方法和数组下标。
if(document.getElementsByTagName('p').length>0){
document.getElementsByTagName('p').item(0);
document.getElementByTagName('p')[0];
}
- getElementsByClassName
- querySelector():只返回匹配的第一个元素
- querySelectorAll():返回的是NodeList
document.querySelectorAll(".dropcap",".huge");
处理属性节点
- getAttribute
- setAttribute
- removeAttribute
- hasAttribute
处理文本节点并修改其内容
- innerHTML
遍历DOM
- parentNode
- previousSibling
- nextSibling
- firstChild
- lastChild
在DOM中动态地添加和移除节点
- createElement
- createTextNode
- appendChild
- removeChild
var p=document.createElement('p');
var text=p.createTextNode('Hello World!');
targetArea.appendChild(text);
targetArea.remove(text);
javascript数据存储
- 变量
- 字符串
- 数值:数值不带引号
- Boolean
- 数组:数组下标从0开始,数组可以容纳各种类型的元素,字符串,数值,对象,其他数组,表达式,或布尔值
数组对象的方法使用
- join
- slice
- shift unshift
- pop
- concat
- sort
变量,函数及循环
- 匿名函数:每个函数内部所定义的变量,都不能在那个函数外面使用。匿名函数有一个优势,若是把某段代码包裹到匿名函数中,则那些原本会落入全局作用域中的变量,现在就全都被局限在该匿名函数内部了。
(function(){
var greeting="Hello Tim";
alert("in scope:"+greeting);
})();
alert("out of scope:"+typeof(greeting));
- 回调函数:当你用某个函数调用另一函数时,后者就叫回调函数,回调函数与普通函数一样,只不过它是在别的函数中执行。回调函数非常适合用于将某个功能划分为不同的层次,以提升代码的可复用性。
function sayHello(message){
alert(message);
}
(function(){
var greeting="Welcome",
exitStatement="Ok,please leave.";
sayHello(greeting);
sayHello(exitStatement);
})
返回数据
- 将返回值传给另一个函数
function sayHello(greeting,exitStatement){
var newGreeting=greeting+"!",
newExitStatement=exitStatement+"!";
return [newGreeting,newExitStatement];
}
function start(polite,rude){
var greeting=sayHello(polite,rude)[0],
exit=sayHello(polite,rude)[1];
alert(greeting+"---"+exit);
}
start("thankyou","you thiink");
一个简单的通讯录
var contacts={
"address":[
{
"name":"Mary",
"email":"mary@example.com"
},
{
"name":"Jane",
"email":"jane@example.com"
},
{
"name":"linda",
"email":"linda@example.com"
}
]
};
(function(){
var object=contacts.address,
contacts_count=object.length;
target=document.getElementsByTagName('body')[0];
i;
if(contacts_count>0){
for(i=0;i<contacts.length;i++){
var item=object[i];
var name=item.name;
var email=item.email;
target.innerHTML+=' <p><a href="mailto:'+email+' ">'+name+'</a></p>';
}
}
}) ();
事件监听器
- 在IE浏览器中添加事件监听器时所需的备用代码
var btn=document.getElementById("btn");
if(btn.addEventListener){
btn.addEventListener("click",function(){
alert("click the button");
},false);
}else{
element.attachEvent("click",function(){
alert("click the button");
});
}
- 解除事件绑定
if(btn.removeEventListener){
btn.removeEventListener("click",alertMessage,false);
}else{
btn.detachEvent("click",alertMessage);
}
- click事件
- focus blur事件:focus事件与提升网站的易访问性有关,以下三种方式都可以激活输入框 1.用鼠标点击它 2.用鼠标点击它旁边的标签 3.通过Tab键切换到它
- change事件
- mouseover mouseout事件
- submit事件
- keydown keypress keyup事件
目前为止代码总结
(function(){
var contacts={
"address":[
{
"name":"Mary",
"email":"mary@example.com"
},
{
"name":"Jane",
"email":"jane@example.com"
},
{
"name":"linda",
"email":"linda@example.com"
}
]
};
var searchForm=document.getElementById('search-form'),
searchField=document.gteElementById('search-form'),
getAllButton=document.getElementById('get-all'),
count=contacts.address.length;
target=document.getElementById('output');
var addr={
search:function(event){
var searchValue=searchField.value,
i;
event.preventDefault();
target.innerHTML="";
if(count>0&&searchValue !==""){
for(i=0;i<count;i++){
var obj=contacts.address[i],
isFound=obj.name.indexOf(searchValue);
if(isFound !==-1){
target.innerHTML+='<p>'+obj.name+'</p>';
}
}
}
},
getAllContacts:function(){
var i;
target.innerHTML="";
if(count>0){
for(i=0;i<count;i++){
var obj=contacts.address[i];
target.innerHTML+='<p>'+obj.name+'</p>';
}
}
},
getActiveSection:function(){
this.parentNode.setAttribute("class","active");
},
removeActiveSection:function(){
this.parentNode.removeAttribute("class");
},
addHover:function(){
searchForm.setAttribute("class","hovering");
},
removeHover:function(){
searchForm.removeAttribute("class");
}
};
serachField.addEventListener("keyup".addr.search,false);
searchField.addEventListener("focus",addr.setActiveSetion,false);
searchFiled.addEventListener("blur",addr.removeActiveSetion,false);
getAllButton.addEventListener("click",addr.getAllContacts,false);
searchForm.addEventListener("mouseover",addr.addHover,false);
searchForm.addEventListener("mouseout",addr.removeHover,false);
searchForm.addEventListener("submit",addr.search,false);
}) ();
触摸及方向变换事件
- touchstart和touchend
- touchmove
- orientationchange
Ajax
- 创建XMLHttpRequest对象:跨浏览器兼容性问题
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}else if(window.ActiveXObject){
xhr=new ActiveXObject("Msxm112.XMLHTTP");
}
- GET与POST的性能对比
获取信息时就用get,提交信息就用post
如果要以Ajax调用传输敏感数据,则应通过post方式,若数据不敏感,则最好采用get方式
但是大多数情况下,get请求的性能都比post好 - open方法:该方法并不做任何实际的事情,只是收集必要的信息,为待执行的调用语句做准备工作而已。
3个参数表示传输调用请求所用的方式,带获取的文件或URL,是否以异步方式调用脚本的boolean标志(大多设置为ture,异步调用),此外还有两个可选参数,用户名和密码 - send方法:在通过open()方法把Ajax调用所需的数据都准备好了,就可以用send()方法送出这些数据和请求,在之后的等待过程中,不断查询readyState属性。
- 接受服务器传回的数据
提出请求后,Ajax队对象会开放一个新的readyState属性,同时还会有一个名为readyStatechange的事件与之关联。 - readyState属性5个值
0——open方法尚未被调用
1——open方法已被调用,send方法未被调用
2——send方法已被调用,请求已送出
3——开始回传服务器的应答
4——请求已完成 - 服务器状态
404——页面未找到
304——文档内容自上次发送请求以来并未改变
500——内部服务器错误
200——服务器正常 - 服务器响应
除了readyState与status之外,Ajax对象也会将调用者所请求的数据作为属性返回。根据开发者在通信时所选择的数据格式,返回的可以是字符串,也可以是XML。先找到Ajax对象,通过responseText和responseXML来获取。 - 将Ajax调用封装为函数
function getHttpObject(){
var xhr;
if(window.XMLHttpRequest){
xhr=window.XMLHttpRequest();
}else if(window.ActiveXObject){
xhr=new ActiveXObject("Msxm12.XMLHTTP");
}
return xhr;
}
function ajaxCall(dataUrl,outputElement,callback){
var request=getHTTPObject();
outputElement.innerHTML="Loading";
request.onreadystatechange=function(){
if(request.readystate===4 && request.status===200){
var contacts=JSON.parse(request.responseText);
if(typeof callback==="function"){
callback(contacts);
}
}
}
request.open("GET",dataUrl,true);
request.send(null);
}
(function(){
var addr={
search:function(){
var output=document.getElementById("output");
ajax('data/contacts.json',output,function(data){
var searchValue=searchFiled.value,
addrbook=data.address,
count=addrbook.length,
i;
event.preventDefault();
target.innerHTML="";
if(count>0&&searchValue !==""){
for(i=0;i<count;i++){
var obj=addrbook.address[i],
isFound=obj.name.indexOf(searchValue);
if(isFound !==-1){
target.innerHTML+='<p>'+obj.name+'</p>';
}
}
}
}
searchForm.addEventListener("submit",addr.search,false);
}) ();
javascript开发模式-
- 函数与闭包模式
该模型利用闭包将所有的内容封装成一个对象,并且在不暴露那个对象其他函数和局部变量的情况下,创建出一整套可以在整个应用程序中使用的公共API
<div id="controls">
<input id="play" type="button" value="play" />
<input id="stop" type="button" value="stop"/>
</div>
var controls=function(el){
var audioControls=el,
playButton=document.getElementById("play"),
stopButton=document.gteElementById("stop");
playButton.addEventListener("click",play,false);
stopButton.addEventListener("click",stop,false);
function play(){
audioControls.setAttribute("class","playing");
}
function stop(){
audioControls.setAttribute("class","stoped");
}
return play,stop;
};
(function(){
var element=document.getElementById("controls"),
action=controls(element);
action.play();
action.stop();yg'
})
设置好事件监听器后,就声明了实际的play和stop函数,这两个函数都使用了那个保存了el参数的audioControls变量,此变量定义在函数之外,却在父对象controls内部。这个实例表明,定义在父对象里面的变量,其作用域可以延伸至同一对象中的其他函数内。
- 事件驱动模式:较前者更为直接,只需设置好函数,然后在事件监听器里调用它们即可
function play(){
this.parentNode.setAttribute("class","playing");
}
function stop(){
this.parentNode.setAttribute("class","stoped");
}
(function(){
var playButton=document.getElementById("play"),
stopButton=document.getElementById("stop");
playButton.addEventListener("click",play,false);
stopButton.addEventListener("click",stop,false);
}) ();