DOM编程艺术学习笔记

DOM编程:(学习书籍为Java DOM编程艺术)

<script>标签建议放在文档最后,</body>之前

1.DOM提供的五个方法:

getElementById() 返回一个对象

getElementByTagName()返回一个对象数组

getElementByClassName()返回一个对象数组

getAttribute(attribute)获取属性值

setAttribute(attribute,value)改变属性值

细节:setAttribute(attribute,value)方法不改变文档源代码,说明DOM工作模式:先加载文档静态内容再动态刷新。DOM的真正威力:对页面内容进行刷新却不需要在浏览器里面刷新页面。

2.事件调用函数

在onclick事件处理函数里加一条return false;,就可以防止用户被带到目标链接窗口(a标签)。

3.DOM的一些新属性

childNodes返回全部子元素数组

nodeType返回节点类型:值1:元素结点 2:属性节点 3:文本节点(由此可以只对特定类型节点进行处理)

nodeValue得到节点值

使用nodeValue注意,诸如<p>元素里的文本是另一种节点,是<p>元素的第一个子节点

firstChild

lastChild

 

2019.5.8

1.分离java script

将代码打包在函数xx中,然后用windows.οnlοad=xx;可以使含有document对象的js代码正常运行(P69)

2.向后兼容

对象检测技术:一定要将方法名后的括号去掉,否则测试的将是方法的结果

if(!document.getElementById) return false;

3.平稳退化,确保可访问

2019.5.20

共享onload事件:多个函数需要在页面加载时执行

window.οnlοad=firstfunction;
window.οnlοad=secondfunction;

这么做的话,只有secondfunction会被绑定,因为前面的值被后面的值覆盖了。那么该怎么办?

方法1:匿名函数

window.onload=function(){
firstFunction();
secondFunction();
}
    

方法2:(推荐使用)addLodEvent函数,将那些在页面加载完毕时执行的函数创建为一个队列

function addLoadEvent(func) {
    var oldonload = window.onload;//将现有的事件处理函数的值存入变量中
    if (typeof window.onload != 'function') {
        window.onload = func;//如果这个事件处理函数没有绑定任何函数,就把新函数添加给它
    } else {
        window.onload = function() {
            oldonload();
            func();//如果已经绑定了函数,就把新函数追加到现有指令的末尾
      }
    }
}

2019.7.9

nodeName属性只返回大写字母

下面给出书上例子的js最终代码

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;
}

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");//links代表id为imagegallery的列表中的a标签集合
  for ( var i=0; i < links.length; i++) {
    links[i].onclick = function() {
      return showPic(this)?false:true;//如果showpic返回true,我们就返回false,浏览器就不会打开链接(阻止默认行为)。
	}
    links[i].onkeypress = links[i].onclick;//onkeypress模仿onclick行为,目的是为了只使用键盘用户,不过书中最后并没有使用。
  }
}

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

addLoadEvent(prepareGallery);

到目前为止,所做的优化有:

1.引入多项测试和检查,使js代码平稳退化

2.最重要的是将事件处理函数分离到了一个外部的js文件。js代码不再依赖HTML文档的内容和结构

3.不使用onkeypress,使js代码的可访问性得到保证(onkeypress函数用户每按下一个按键都会触发,意味着只要onkeypress事件处理函数返回的是false,用户将永远无法离开当前链接。上述showpic函数如果成功返回的就是false)

依然存在的问题:

placeholder和description(图片展示和文字描述)只为showpic函数而存在,不支持js的浏览器最好不呈现这两个元素。

因此,接下来学习如何使用DOM提供的方法属性去创建HTML元素,并把他们插入HTML文档。

第七章 动态创建标记

1.一些传统方法

document.write():js与html混杂,不推荐

innerHTML属性:该属性无细节可言,一旦使用了这个属性,它的全部内容都将被替换。同时innerHTML是HTML专有属性,不适用任何其他标记语言文档。

2.DOM方法 (并不是在创建标记,而是在改变节点树。

创建一个元素,把这个元素加到节点树

2.1 createElement:创建一个元素节点

把结果赋值给一个变量是一个好主意

例如 var para=document.createElement("p")

2.2 appendChild

把新创建的节点插入节点树的最简单的方法就是:让它成为这个文档某个现有节点的一个子节点

parent.appendChild(child)

2.3 createTextNode:创捷文本节点

var txt=document.createTextNode(text)

 

3.1在已有元素前插入一个元素

parent.insertBefore(newElement,targetElement)

不必在乎parent具体是哪个,targetElement的parentNode属性值就是它。

例:把A插入到B前

B.parentNode.insertBefore(A,B)

3.2在已有元素后插入一个元素

没有现成函数使用,可以自己写一个

function insertAfter(newElement,targetElement) {
  var parent = targetElement.parentNode;
  if (parent.lastChild == targetElement) {
    parent.appendChild(newElement);     //如果targetElement是父元素最后一个子元素,那么刚好直接添加就可以
  } else {
    parent.insertBefore(newElement,targetElement.nextSibling);//如果不是,则插在targetElement的下一个兄弟元素前
  }
} 

nextsibling属性:下一个兄弟节点

 

4 Ajax(异步加载页面的技术)

4.1XMLHTTPRequest对象

function getHTTPObject() {
  if (typeof XMLHttpRequest == "undefined")
    XMLHttpRequest = function () {
      try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
        catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
        catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP"); }
        catch (e) {}
      return false;
  }
  return new XMLHttpRequest();
}

var request=getHTTPObject();

open方法,用来指定服务器上将要访问的文件,指定请求类型GET/POSY/SEND,第三个参数指定请求是否以异步方式发送和处理。

request.open("GET","example.txt",true)

onreadyStatechange:是一个事件处理函数,他会在服务器给XMLHTTPRequest对象送回响应的时候被触发执行。

可以指定一个处理函数

request.onreadyStatechange=function(){

//处理响应

}

也可以引用一个函数

request.onreadyStatechange=doSomething;(不加括号,加括号表示立即调用)

在指定了请求目标,也明确如何处理之后就可以用send方法发送请求了。

request.send(null);

这里可能会遇到XMLHTTPRequest对象不支持的问题,当浏览器向XMLHTTPRequest对象发回响应的时候,浏览器会在不同阶段更新readyState属性的值,他有5个可能的值:

  • 0 表示未初始化
  • 1 表示正在加载
  • 2 表示加载完毕
  • 3 表示正在交互
  • 4 表示完成

只要readyState属性的值变成了4,就可以访问服务器发回来的数据了。

访问发回的数据时,需要通过两个属性

responseText 保存文本字符串形式的数据        例如var txt=document.createTextNode(request.responseText);

responseXML 保存Content-Type头部中指定为“text/xml”的数据,其实是一个DocumentFragment对象

使用Ajax时,要注意同源策略,使用XMLHTTPRequest对象发送的请求只能访问与其HTML处于同一个域中的数据

异步请求有一个容易被忽略的问题就是异步性,脚本在发送XMLHTTPRequest请求之后,仍然会继续执行,不会等待响应返回。

Ajax应用只要依赖服务器端处理,而非客户端处理。

Ajax会在12章更具体的介绍。

第八章  充实文档的内容

本章具体介绍了一些实例,比如把文档中的缩略语显示为一个缩略语列表(因为缩略语<abbr>标签的title属性用户不可见),下面仅仅写一些我认为重要的点。

直接上完整代码:

function displayAbbreviations() {
  if (!document.getElementsByTagName || !document.createElement || !document.createTextNode) return false;
// 获取所有abbr元素
  var abbreviations = document.getElementsByTagName("abbr");
  if (abbreviations.length < 1) return false;
  var defs = new Array();
// 遍历
  for (var i=0; i<abbreviations.length; i++) {
    var current_abbr = abbreviations[i];
    if (current_abbr.childNodes.length < 1) continue;//因为低版本IE不支持abbr元素,所以返回abbr元素的子节点为0.如此就就立刻开始下一个循环。
    var definition = current_abbr.getAttribute("title");//title属性保存的是全称。
    var key = current_abbr.lastChild.nodeValue;//其实就是文本节点,abbr元素有且仅有一个子节点。也就是缩写
    defs[key] = definition;//比如def["w3c"]="World Wide Web Consortium"
  }
// 创建定义列表
  var dlist = document.createElement("dl");
// loop through the definitions
  for (key in defs) {
    var definition = defs[key];
// 创建定义标题
    var dtitle = document.createElement("dt");
    var dtitle_text = document.createTextNode(key);
    dtitle.appendChild(dtitle_text);
// 创建定义描述
    var ddesc = document.createElement("dd");
    var ddesc_text = document.createTextNode(definition);
    ddesc.appendChild(ddesc_text);
// 把他们添加到定义列表
    dlist.appendChild(dtitle);
    dlist.appendChild(ddesc);
  }
  if (dlist.childNodes.length < 1) return false;//因为低版本IE不支持abbr元素defs数组就是空的,自然dl元素也没有子节点,如此便退出函数。
// 创建标题
  var header = document.createElement("h2");
  var header_text = document.createTextNode("Abbreviations");
  header.appendChild(header_text);
// 把标题添加到页面主体
  document.body.appendChild(header);
// 把定义列表添加到页面主体
  document.body.appendChild(dlist);
}
addLoadEvent(displayAbbreviations);

另外两个例子大同小异。其中有个需要把提取出来的文献来源链接添加到blockquote元素最后的地方,这里就存在一个问题。

例子中结尾</p>和</blockquote>之间存在一个换行符,有些浏览器会把这当成一个文本节点,所以用lastChild属性就不对了。

解决办法:

// 取得当前blockquote元素包含的所有元素节点
    var quoteChildren = quotes[i].getElementsByTagName('*');
// 如果没有,就退出本次循环
    if (quoteChildren.length < 1) continue;
//因为getElementsByTagName获取的都是元素节点,自然而然最后一个就是我们需要的
    var elem = quoteChildren[quoteChildren.length - 1];

TIPS:如果没有百分之百的把握,需要去检查nodeType的值,有很多DOM方法只能用于元素节点。用在文本节点就会出错。

第九章 CSS-DOM

本章主要介绍用js去设置css属性。

首先介绍一个style属性,查询这个属性返回的是一个对象,样式都存放在这个对象的属性了,可以读写。

用法:element.style.property

  • style对象只包含在HTML代码里用style属性声明的样式,但这几乎没有实用价值。
  • style对象的属性值永远是一个字符串。
  • style对象的属性值必须放在引号里,单双引号都可以,否则会认为等号右边是一个变量。

如何寻找下一个元素节点?

function getNextElement(node) {
  if(node.nodeType == 1) {
	return node;
  }
  if (node.nextSibling) {
    return getNextElement(node.nextSibling);
  }
  return null;
}

固然可以用DOM直接设置或修改样式,但这样行为层就干预了表示层,后期修改也麻烦,有一种更好的做法:

与其使用DOM直接改变某个元素的样式,不如通过JavaScript代码去更新这个元素的class属性

可以用setAttribute函数来做这个事情。更简单的办法是更新className属性,className是一个可读可写的属性。这样修改样式只需要修改css文件。

这个技巧只有一个不足:每次都是替换(而不是追加)该元素的原有的的class设置。编写一个函数来解决这个问题

function addClass(element,value) {
  if (!element.className) {    //如果原有设置为空
    element.className = value;
  } else {                     //不为空则追加
    element.className+= " ";
    element.className+= value;
  }
}

第十章 用JavaScript实现动画效果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值