本书在一些基础的JavaScript语法上,通过一个个小例子讲解了简单的dom操作,最后把例子综合起来做成一个网站。难得可贵的是其中的平稳退化,渐进增强的web设计理念——确保页面在没有JavaScript的情况下也能正常工作。其中对兼容性的考虑和结构、样式、行为相分离的思想也是值得学习的。
1. 什么是JavaScript
JavaScript是一种运行在浏览器端的脚本语言。JavaScript主要包括ECMAscript(规定标准JavaScript的语法)、BOM(浏览器窗口对象的一组API )、和重要的DOM(文档对象模型,即如何操作文档,对文档的内容进行抽象和概念化的方法)。
至于JavaScript的弱类型语言、解释性语言和基于原型的特性在此不再赘述。
2.通用型函数
- onload让函数在网页加载完毕后立即执行。else,如果window.onload上已经绑定了函数,那么就将新函数追加到现有指令下面。
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
- inserAfter函数在元素后插入一个新元素。 如果目标元素是其父元素的最后一个子元素,那么就插入在其父元素后面;如果不是,那么就插入在目标元素的下一个兄弟元素前面。
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement) {
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
- 类jQuery的addClass()添加类名函数
function addClass(element,value) {
if (!element.className) {
element.className = value;//如果没有类名则直接添加
} else {
newClassName = element.className;
newClassName+= " ";
newClassName+= value;//如果有类名将其转化为字符串连接起来
element.className = newClassName;
}
}
3. JavaScript图片库
function prepareGallery() {
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");
for ( var i=0; i < links.length; i++) {
links[i].onclick = function() {
return showPic(this);
}
links[i].onkeypress = links[i].onclick;
}
}
这里prepareGallery函数获得图片库每个a标签的值,并对他们执行showPic函数。这里前三句可以保证浏览器部分不支持JavaScript或者imagegallery不存在时脚本也可以正常工作,即渐进增强。
function showPic(whichpic) {
if (!document.getElementById("placeholder")) return true;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if (!document.getElementById("description")) return false;
if (whichpic.getAttribute("title")) {
var text = whichpic.getAttribute("title");
} else {
var text = "";
}
var description = document.getElementById("description");
if (description.firstChild.nodeType == 3) {
description.firstChild.nodeValue = text;
}
return false;
}
这里showPic函数将获得a标签的src和alt属性,并将其赋值给placeholder。配合prepareGallery可以实现点击a标签更新img标签placeholder的src属性和p标签description的nodevalue,从而做到图片切换的效果。
优点:
- 将onclick事件处理程序从a标签中解放出来,不仅做到结构和行为相分离,而且简化了代码。
- 把showPic函数单独抽象出来,其中的whichpic参数通过传入不同的参数,使showpic函数具有一定的普适性(组件化)。
- 遍历a标签,对每个标签执行showpic函数,而不是每个a标签依次调用showpic函数,简化了代码,return false取消a链接默认的跳转行为。
后面还会介绍将缩略图包含在a标签内,使页面更美观。结构和行为相分离的理念要求我们动态生成img标签placeholder的src属性和p标签description,因为这些标签仅仅是为了showpic函数服务的。结构和行为分离固然很好,但这同时也会增加js的代码量,其中的平衡也是实际开发中要考虑的因素。
4. Ajax异步加载页面技术
优势:
- 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
- 用户可以继续浏览页面并与页面交互,通过ajax可以按需加载和创建页面内容,而不会打断用户的浏览体验,从而使web应用呈现出功能丰富,交互敏捷,类似桌面应用般的体验。
XMLHttpRequest是ajax技术的核心,用于在后台与服务器交换数据。ajax承担浏览器和服务器端的中间人的角色,JavaScript通过ajax可以自己发送请求,也可以自己处理相应。
- 创建ajax对象
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
- 向服务器发送请求
将请求发送到服务器,我们使用XMLHttpRequest对象的open()方法。
open(method,url,async);
method:请求的类型;GET 或 POST;url:文件在服务器上的位置;async:true(异步)或 false(同步);大部分情况下使用GET类型。
- 请求实例
`
function getNewContent(){
var request = getHTTPObject();//创建ajax对象
if(request){
request.open("GET","example.txt",true);//向服务器端(此处是txt文件)发送请求
request.onstatechange = function(){
if(request.readyState == 4){//readyState为4即请求成功
var para = document.createElement("p");
var txt = document.createTextNode(request.responseText);
para.appendChild(txt);
document.getElementById("new").appendChild(para);//将请求的内容插入到id为new的div中
}
};
request.send(null);//将请求发送到服务器 string类型
}else{
alert("Sorry,your browser does not support ajx")
}
}
addLoadEvent(getNewContent);
`
5. 实现移动元素效果
function moveElement(elementID,final_x,final_y,interval) {//参数代表元素id 最终xy位置 移动速度
if (!document.getElementById) return false;
if (!document.getElementById(elementID)) return false;
var elem = document.getElementById(elementID);
if (elem.movement) {//属性不会产生局部变量和全局变量的作用域问题 清除定时器
clearTimeout(elem.movement);
}
if (!elem.style.left) {
elem.style.left = "0px";
}
if (!elem.style.top) {
elem.style.top = "0px";
}
var xpos = parseInt(elem.style.left);
var ypos = parseInt(elem.style.top);
if (xpos == final_x && ypos == final_y) {
return true;
}
if (xpos < final_x) {
var dist = Math.ceil((final_x - xpos)/10);//这个公式可以实现移动动画先快后慢的效果
xpos = xpos + dist;
}
if (xpos > final_x) {
var dist = Math.ceil((xpos - final_x)/10);
xpos = xpos - dist;
}
if (ypos < final_y) {
var dist = Math.ceil((final_y - ypos)/10);
ypos = ypos + dist;
}
if (ypos > final_y) {
var dist = Math.ceil((ypos - final_y)/10);
ypos = ypos - dist;
}
elem.style.left = xpos + "px";
elem.style.top = ypos + "px";
var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
elem.movement = setTimeout(repeat,interval);//setTimeout递归调用自己可以实现类似setInterval每一帧结束后再次调用定时器的功能
}//但是递归调用浪费空间时间,存在效率问题
利用此函数可以实现图片切换或者轮播之类的效果。
6. 最后的综合项目 即大作业
预览效果: https://richardyou.github.io/JavaScript-DOM-/index.html
代码地址:https://github.com/richardyou/JavaScript-DOM-