JS DOM编程艺术学习笔记(一)

JS DOM编程艺术学习笔记

什么是DOM,简单的来说就是一套对文档的内容进行抽象和概念化的方法。

第二章 JavaScript 语法

把JavaScript代码存为一个扩展名为.js的独立文件,并在文档的`<head>`部分,或HTML文档的最后`</body>`之前,放一个`<script>`标签,
并把它的src属性指向改文件:
            <script src="file.js"></script>
  1. 注释:

    单行注释:// (HTML里是<!--……-->)
    多行注释:/*……*/

  2. 变量:

    声明变量:var a,b,c;

    变量名允许包含字母,数字,美元符号,下划线(但第一个字符不准是数字),不允许包含空格或标点符号。通常,变量命名是用下划线分隔各个单词

  3. 数据类型

    a)字符串:var mood=”happy”;(单引号也行;如果字符串包含单引号,就把整个字符串放在双引号里;如果单词中含单引号,如don’t,单引号需要被看成一个普通字符,这种情况要对字符串进行转义,即用到反斜杠don\’t,双引号类似)
    b)数值:var age=18;(支持负数,浮点数)
    c)布尔值:var sleeping=true;(false,千万不要用引号括起来!菜鸟第一次面试实习,而且是非常想进的网易的时候,居然加了引号,悔啊T—T……估计小哥主管一下就把我拍死了)
    d)对象:每个值都是对象的一个属性(见后)
    e)数组:var X=Array();
    可以用关键词Array声明,括号里也可以给出数组长度;
    向数组中添加元素的操作称为填充:X[index]=element;(注意!数组里下标是从0开始!)我们只需要用一对方括号把各个元素的初始值括起来就可以了:var beatles=[“Jonh”,”Paul”,”Sun”];
    数组还可以包含其他数组,现在beatles数组的第一个元素就是lenno数组,想要获得那个数组里的某个元素就要使用更多的方括号:如beatles[0][0];

var lenno=["Jonh",1940,false];
var beatles=[];
beatles[0]=lenno;

4.函数

如果多次使用同一段代码,就把它封装成函数。
语法:function name(arguments){    statements;     }
javascript的内建函数有:alert、confirm、join、length、reverse、getDate、sqrt、round等(有单独一篇文章介绍)
函数的真正价值在:可以把一个函数的调用结果赋给一个变量
驼峰格式是函数名,方法名和对象属性名的首选格式,如myName。
注意!如果某个函数中使用var,则变量视为局部变量。如果没有使用var那么变量将被视为全 局变量。如果脚本里已经存在与之同名的全局变量,
这个函数就会改变那个全局变量的值。为了避免二义性隐患,定义一个函数时,我们要把它的内部全都用var明确的声明为局部变量

5.对象

JS里对象可以分为三种类型:用户自定义对象,内建对象和宿主对象(浏览器提供,如window对象)
对象里的数据可以通过属性和方法访问,用“.”的语法。
给对象创造新的实例:var Jeny=new Person;
内建对象:
数组Array——属性length,join()数组中所有字符相连的字符串,reverse()逆转,sort数组元素排序)
字符串String——属性length
数学对象Math,不能用new
布尔量Boolean,
日期时间Date——getDay(),getHours(),getMonth()
宿主对象:Form,Image,Element等

第三章 DOM

D:document     O:object     M:model(map)
5个常用的DOM方法,getElementById,getElementsByTagName, getElementsByClassName, getAttribute 和 setAttribute     
DOM把一份文档表示为一棵节点树

1.节点

元素节点:DOM的原子,标签的名字就是元素的名字
文本节点:<p>包含在元素节点内部,可在一些<li>内部
属性节点:用来对元素做出更具体的描述,几乎所有的元素都有title属性

2.获取元素

 都可以先赋给一个变量,再进行操作
 getElementById(id):返回一个对象,该对象对应此id属性值的元素节点。
 getElemrntsByTagname(tag):返回一个对象数组,分别对应着文档里的一组特定元素节点。通配符“*”如果想知道
 一个文档里有多少个元素节点可以写成getElementsByTagName("*").length
 构造function genElementsByClassName(node,classname)搜索起点

3.获取和设置属性

上述是获取特定元素的方法,得到需要的元素后就可以获取他的各个属性,即getAttribute()。相应的setAttribute()可以更改属性节点的值。

getAttribute是一个函数,只有一个参数——你打算查询的属性名字,object.getAttribute(attribute)
    //一段可读性比较好的小代码
    var paras=document.getElementsByTagName("p");
        for(var i=0;i<paras.length;i++){
            var title_text=paras[i].getAttribut("title");
            if(title_text) alert(title_text);
        }
    }
   //if(title_text!=null)可简写,if里面如果something存在,则if条件为真
setAttribute用来设置元素的属性object.setAttribute(attribute,value)
在动态刷新,动态刷新不影响文档里的静态内容。这正是DOM的真正威力:对页面内容进行刷新却不需要再浏览器里面刷新页面。

第四章 案例探究:JavaScript图片库
用JavaScript和DOM建立一个图片库

为每张图片分别创建一个网页的解决方案值得考虑,这样你的图片库将不再是一个体积庞大,难以下载的网页,而变成许多尺寸合理、便于下载
和浏览的页面。利用JavaScript来创建图片库是最佳选择,把整个图片库的浏览链接集中安排在图片库主页里,只在用户点击这个主页的某个链接
时才把相应的图片传送给他。

第一步:为这些图片创建一个链接清单,<ul>或<ol>,并把图像集中保存在目录images里。清单里的每个链接分别指向不同的图片,
点击可以转到相应的图片,但从图片返回到链接清单需要借助Back.
<body>
        <h1>Happy</h1>
        <ul>
            <li><a href="images/image_0001.jpg" title="Happy1">Happy1</a></li>
            <li><a href="images/image_0002.jpg" title="Happy1">Happy2</a></li>
            <li><a href="images/image_0003.jpg" title="Happy1">Happy3</a></li>
            <li><a href="images/image_0004.jpg" title="Happy1">Happy4</a></li>
            <li><a href="images/image_0005.jpg" title="Happy1">Happy5</a></li>
            <li><a href="images/image_0006.jpg" title="Happy1">Happy6</a></li>
        </ul>
</body>
第二步:改进——当点击链接时,留在这个网页,并同时看到图片和原有图片清单。方案:“占位符”图片在这个网页上为图片预留一个浏览区域,
用id属性进行设置,这使我们可以通过外部样式表对图片显示位置和显示效果进行控制。
<img id="holder" src="images/holder.jpg" alt="My image gallery"/>
第三步:Javascript。为了把“占位符”图片替换为想要查看的图片,需要改变他的src属性。setAttribute函数,这个函数的唯一参数就是图片链接。
它通过改变占位符图片的src属性将其替换为参数图片。
<script> function showPic(whichpic){ var placeholder=document.getElementById("holder"); var source=whichpic.getAttribute("href"); placeholder.setAttribute("src",source); } </script>
第四步:应用JavaScript函数与文档结合。把函数保存扩展名为.js文件中(最好将.js文件合并到一个文件中,减少对站点的请求次数)。
然后在文档</body>之前插入链接来引用这个js文件。
再需要给图片列表的链接添加行为,也就是事件处理函数。用到this关键字,表明这个对象。注意!还要阻止默认弹出新网页行为,
可以设置一个返回值false,让onclick函数认为"这个链接没有被点击"也就是链接不会真的被打开。
<li><a href="images/image_0001.jpg" title="Happy1" onclick="showPic(this); return false;">Happy1</a></li>

扩展:在同一网页上切换显示不同文本

图片库里的每个图片链接都有一个title属性,可以把这个属性取出来并让他和相应的图片显示在同一
网页上:var text=witchpic.getAttribute('title');还需要用到几个新DOM属性:
创建一个文本节点,先为文本安排一个位置,<p id="description">Choose a image.</p> 当图片链接被点击时,不仅要把“占位符”图片
替换为链接href属性指向的图片,还要把文本同事换位那个图片链接的title值。(这里没有按原书写,我觉得这样更简单,书上用到属性childNodes,
nodeType,nodeValue,并使用firstChild,nodeValue属性)
function showPic(whichpic){
    var placeholder=document.getElementById("holder");
    var description=document.getElementById("description");
    var source=whichpic.getAttribute("href");
    var text=whichpic.getAttribute("title");
    placeholder.setAttribute("src",source);
    description.innerHTML=text;
}
 简单说一下书中介绍的方法:nodeValue属性——改变一个文本节点的值,childNode属性——是一个包含在这个元素的全部子元素的数组,
 child[0]又称为firstChild,表示第一个元素。上面代码最后一行也可写成:description.firstChild.nodeValue=text;

 样式学习:在<head>里用一个<link>标签引入外部样式
 <link rel="stylesheet" href="styles/layout.css" media="screen"/>
  background-color:transparent;(透明的意思)
  text-docoration:none;(none: 定义正常显示的文本 underline: 定义有下划线的文本 overline: 定义有上划线的文本 
  line-through: 定义直线穿过文本 blink: 定义闪烁的文本)
  display:inline 列表项从纵向显示变为横向显示

第五章 最佳实践

您的网站访问者可能未启动JavaScript功能,浏览器对JavaScript的支持程度也不一样。
  1. 平稳退化经典例子:href属性设置为真实存在的URL地址,即使Javascript被禁用,或遇到搜索机,这个链接也是可用的。

  2. 分离JS代码和HTML文件。尤其是内嵌的时间处理函数如onclick,在HTML里使用如onclick之类的属性是没有效率和容易引发问题的做法。
    我们可以在外部Javascript文件里把一个事件添加到HTML文档中某个元素上。语法:element.event=action,
    如getElementById(”).onclick=function(){}
    如果事件涉及多个元素,我们可以使用getElementsByTagName,和getAttribute,即把文档里的所有连接放入一个数组,
    然后遍历数组。

var links=document.getElementsByTagName("a");
for(var i=0;i<links.length;i++){
        links[i].onclick=function(){
            ……
            return false;
        }
}
 如果<script>标签位于</body>之前,需要用到window.onload=来保证js文件在文本加载完成时才触发

3.如何检测浏览器对JavaScript的支持程度?在使用某个特定方法或属性之前,先测试它是否真 实存在是确保向后兼容性最安全
可信的方法。只要把某个方法打包在if语句里就能实现,而且测试条件用“逻辑非”运算符可以简化代码。

    if(!getElementById) return false;  
如果测试多个方法或者属性是否存在,可以用“逻辑或”操作符将其合并,如:
    if(!getElementById||!getElementsByTagName) return false;

4.性能考虑:

尽量少访问DOM,如重复使用getElementById,应把第一次搜索的结果保存在一个变量中。尽量减少不必要的标记。
合并脚本js文件,并且把所有<script>脚本放到文档的末尾,</body>标记之前,可以让页面更快。传统上我们都把脚本放在<head>区域
压缩脚本,把脚本中不必要的空格和注释删除。多数情况下,你应该有两个版本,一个是工作副本,可以修改代码并添加注释;
另一个是精简版本,用于放在站点上。文件名中加上min字样。推荐几个代码压缩工具:
雅虎的YUI Compressor(http://developer.yahoo.com/yui/compressor)
谷歌的Closure Compile(http://closure-compile.appspot.com/home)

第六章 图片库改进版

改进一:onclick事件分离
       可以在ul标签中设置id=**,再在js中编写一个简短函数把有关操作关联到onclick事件上。
改进二:确保向后兼容性,检查当前浏览器是否支持getElementById,getElementsByTagName,是否存在id=**元素;尽量少访问DOM,
遍历id=**元素中的所有连接,设置onclick事件。
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;
  }
 改进三:保证HTML加载完成,共享onload事件:  推荐方案——addLoadEvent,把现有的window.onload事件处理函数的值存入变量oldonload。
 如果想把更多函数加到里面,只需要在指令末尾加上:addLoadEvent(function1);addLoadEvent(function2);addLoadEvent(function3);
 ……就可以了,方便以后工作扩展。
    function addLoadEvent(func) {
          var oldonload = window.onload;
          if (typeof window.onload != 'function') {
            window.onload = func;
          } 
          else {
            window.onload = function() {
             oldonload();
              func();
            }
      }

     addLoadEvent(prepareGallery);
改进四:showpic()函数 对出现元素的存在性进行检查,如图片placeholder;描述description元素,和它的第一个子元素是不是文本节点;
链接里的title属性如果不存在,设为空字符串,
function showPic(whichpic) {
  if (!document.getElementById("placeholder")) return false;
  if (!document.getElementById("description")) return false;
  if (whichpic.getAttribute("title")) {
    var text = whichpic.getAttribute("title");
  } else {
    var text = "";
  }
  var source = whichpic.getAttribute("href");
  var description = document.getElementById("description");
  var placeholder = document.getElementById("placeholder");
  placeholder.setAttribute("src",source);

  if (description.firstChild.nodeType == 3) {
    description.firstChild.nodeValue = text;
  }
  return false;
改进五:关于onclick的优化,避免用户使用键盘无法操作,让处理键盘事件的onkeypress事件与onclick触发同样的行为
(一般不用考虑,因为这也会带来一些问题)
for ( var i=0; i < links.length; i++) {
    links[i].onclick = function() {
      return showPic(this);
    }
    links[i].onkeypress = links[i].onclick;
  }

第七章 动态创建标记
本章介绍一些DOM方法,通过创建新元素和修改现有元素来改变网页结构。

1.传统方法

  document.write:HTML专有属性,不能用于其他标记语言文档。快捷的把字符串插入到文档里,缺点是违背了“行为与表现分离”,
  必须在HTML里增加<script>标签,应避免使用
    <script> document.write("<p>This is a paragraph</p>") </script>
 innerHTML:HTML专有属性,不能用于其他标记语言文档,浏览器几乎都支持,已经包含到HTML5规范中。可以用来读、写某给定元素里的HTML内容。
 但是毫无细节可言,就像一把大锤那样粗放,要想获得细节就必须使用DOM方法和属性(终于知道上面为什么写的复杂了),比如:
    <div id="testdiv">            //HTML中
       <p>This is<em>my</em>content.</p>
    </div>
    window.onload=function(){          //js中
            var testDiv=document.getElementById("testdiv");
            alert(testDiv.innnerHTML);
}
  结果为:<p>This is<em>my</em>content.</p>
  大锤有大锤的用武之地,在需要把一大段HTML内容插入网页时,innerHTML属性更合适,既支持读取也支持写入。 但是innerHTML不会返回对任何
  刚插入内容的引用,如果想对刚插入内容进行处理,则需要使用DOM提供的精确的方法和属性。

2.DOM方法

  如果想在节点树上添加内容,就必须插入新的节点。这个任务分成两个步骤,第一步创建新的元素,第二步把新的元素插入节点树。
  注意!DOM方法要测试浏览器兼容性,增加几个if语句来测试document.creatElement,creatTextNode等是否存在

  createElement:创建新的元素,语法:document.creatElement(nodename)如:document.creatElement("p");并养成好习惯,将它赋给一个变量。
  var para=document.creatElement("p");但此时它还不是一棵DOM节点树的组成部分。但已经有了nodeName(大写P),和nodeType(1:元素节点)值。
  appendChild:把新创建的节点插入文档结构,成为id="testdiv"的子节点:语法:parent.appendChild(child)如:testdiv.appendChild(para);
  其中,var testdiv=getElementById("testdiv");
  creatTextNode:创建元素节点并插入文档节点树后,想把一些文本放入这个p元素。语法:document.creatTextNode(text)如:
  document.creatTextNode("Hello");并养成好习惯,将它赋给一个变量:var txt=document.creatTextNode("Hello");
  但此时它还不是一棵DOM节点树的组成部分。再用appendChild把创建的文本节点插入到上面创建的p元素:para.appendChild(txt);
window.onload=function(){
      var testdiv=getElementById("testdiv"); 
      var para=document.creatElement("p");
      testdiv.appendChild(para);
      var txt=document.creatTextNode("Hello");
      para.appendChild(txt);
}
 3.重回图片库
 insertBefore():在已有元素前插入一个新元素需要准备三件事:元素newElement,插入到哪个目标元素之前targetElement,目标元素父元素parentElement。
 语法:parentElement.insertBefore(newElement,targetElement);
 编写insertAfter方法:
  function insertAfter(newElement,targetElement){
    var parent=targetElement.parentNode;
    if(parent.lastChild==targetElement){parent.appendChild(newElement);}
    else {parent.insertBefore(newElement,targetElement.nextSibling);}
    }  

你可能感兴趣的:(JS DOM编程艺术学习笔记(一))