Web全栈笔记之DOM编程艺术

一、代码命名规范:

    1. 变量使用下划线
    2. 函数使用驼峰命名

二、DOM

定义:DOM是一套对文档的内容进行抽象和概念化的方法.

  • D:文档 document
  • O: 对象 object
  • M: 模型 Model

DOM是一种适用于多种环境和多种程序设计语言的通用型API。


1. 文档是由节点构成的集合,只不过此时的节点是文档树上的树枝和树叶而已
2. 一个文档就是一颗节点树
3. 节点分类:
DOM的原子是元素节点(element node)、文本节点(text node)、属性节点(attribute node)

获取元素

通过id获取元素

//getElementById 通过id获取元素
document.getElementById("id");
//文档上每一个元素都是一个对象。利用DOM提供的方法能得到任何一个对象

通过标签名获取元素

//getElementsByTagName方法返回一个对象数组,每个对象分别对应这文档里的有着给定标签的一个元素;
document.getElementsByTagName("li")//返回文档中所有的li标签
//如果你要知道某份文档中总共由多少个元素节点,可以用通配符
document.getElmentByTagName("*").length

通过类名获取元素

//getElmentByClassName,整个方法我们能够通过class属性中的类名类访问元素
//这个方法还可以查找那些带有多个类名的元素,指定多个类名,只要在字符串参数中用空格分隔类名即可。
document.getElmentsByClassName("important sale").length 
//这个getElementsByClassName方法非常有用,但只有比较新的浏览器才支持它,所以呢要自己实现这个方法

function getElementsByTagClassName(node, calssName){
   if(node.getElementsByClassName){
       //使用现有的方法
       return node.getElementsByClassName(calssName);
    }else{
       var results = new Array();
       var elems   = node.getElementsByTagName("*");
       for (var i=0;i<elems.length;i++){
           if(elems[i].className.indexOf(calssName) != -1){
             results[results.length] = elems[i];
           }
          }
    }
   return results;
}

获取和设置属性


1. getAttribute
* 它是一个函数,一个参数---查询属性的名字
* 不属于document对象,不能通过document调用
* object.getAttribute(attribute) 例如:obj.getAttribute("title")//获取标签title属性
2. setAttribute
* 对属性节点的值做出修改
* object.setAttribute(attribute,value)

childNodes属性

//在一棵节点树上,childNodes属性可以用来获取任何一个元素的所有子元素,它是一个包含这个元素全部子元素的数组
element.childNodes
//注意:
//由childNodes属性返回的数组包含所有类型的节点,而不仅仅是元素节点,几乎每一样东西都是一个节点,甚至连空格和换行符都会被解释为节点,而他们全都包含在childNodes属性返回的数组中。

nodeType属性

每一个节点都有nodeType属性
nodeType属性共有12种可取值,但其中仅有3种具有实用价值。
[X] 元素节点的nodeType属性值为1
[X] 属性节点的nodeType属性为为2
[X] 文本节点的nodeType属性值为3

nodeValue属性

* 如果想改变一个文本节点的值,那就使用DOM提供的nodeValue属性,它用来得到一个节点的值:

node.nodeValue

注意:
node应该是该标签的文本节点,只有文本节点才会由nodeValue。
例如: p.nodeValue 得到的是一个null值。 而你真正需要的是<p>元素所包含的文本的值。包含在<p>元素的文本是另一种节点,他是<p>元素的第一个子节点。因此你想要得到的其实是它的第一个子节点的nodeValue的属性值。
所以要这么获得: p.childNodes[0].nodeValue;

* 设置一个节点的值

p.childNodes[0].nodeValue = "666666666";

* nodeName

返回标签名称
nodeName属性总是返回一个大写字母的值
例如: if(placeholder.nodeName != "IMG") return false;

三、DHTML

DHTML是 “Dynamic HTML”(动态HTML)的简称。DHTML并不是一项新技术,而是描述HTML、CSS、JavaScript技术组合的术语。

1、利用HTML把网页标记和各种元素;

2、利用CSS设置元素样式和探秘的显示位置;

3、利用javaScript实时地操控页面和改变样式;

四、JavaScript语法

用javaScript编写的语法必须通过HTML/XHTML文档才能执行。


1. 将JavaScript代码放到文档<head>标签中的<script>标签之间:
2.典型的做法是将JavaScript代码作为一个扩展名为.js的独立文件,再文档的<head>部分放一个<script>标签,并把他的src属性指向该文件;
3.最好是把<script>标签放到HTML文档的最后,<body/>之前,这样能使浏览器更快的记载页面;

语句

多条语句放在同一行上,就必须使用分号来隔开它们:

         first statement;  scond statement;

注释:

1.使用双斜杠
//自我提醒:有注释是好事     
注意点:使用这种注释方式,就必须再每个注释的开头加上两个斜线,例如像下面这样就会出问题
//自我提醒:
  有注释是好

----------------------------分割线---------------------------------------------
2.再注释内容的开头加上一个斜线和一个星号(/*),在注释内容的末尾加上一个星号和一个斜线(/*)

/*自我提醒:
   有注释是好事*/
这种注释方式在需要插入大段的注释时很有用,他可以提高整个脚本的可读性。

----------------------------分割线---------------------------------------------
3. 还可以使用HTML的注释风格,其实JavaScript解析器对"<!--"的处理与对“//”的处理是一样的:
<!--这是JavaScript中的注释
如果在HTML文档中,还需要以"-->"来注释结尾
<!--这是HTML中的注释-->
注意:
1.JavaScript不要求这样坐,它会把“-->”当作注释内容的一部分

2.HTML允许上面那样注释跨越多行,但JavaScript要求每行都必须在开通加上 “<!--” 来作为标志

3.JavaScript解释器在处理这种风格的注释时与大家所熟悉的HTML做法不同,为避免发生混淆,最好不要在JavaScript脚本中使用这种风格的注释。建议大家使用“//”来注释单行,用“/*”注释多行

变量

//对某个变量赋值之前未声名,赋值操作将自动声明该变量。(ps:虽然JavaScript没有强制要求程序员必须提前声明变量,但提前声明变量是一种良好的编程习惯)

    var mood;
    var age;


//不必单独声明每个变量,你也可以用一条语句一次声明多个变量

     var mood, age; 


//也可以一石二鸟:把声明变量和对该变量的赋值一次完成:

     var mood = "happy", age = 33;

//注意点:
//变量和其他语法元素的名字都是区分大小写的(ps:MOOD 和 mood是完全不一样的)
//不允许变量包含空格或标点符号(美元符号“$”除外)


//数据类型(必须明确类型声明的语音成为强类型语言, JavaScript不要进行类型声明,因此他是一种弱类型语言 )



//1. 字符串


//字符串由零个或多个字符构成。字符串包括(但不限于)字母、数字、标点符号和空格。字符串必须包括在引号里,单引号或双引号都可以

   var mood  = ‘happy’;
   var mood2 = "happy"; 都是可行的

//注意:如果字符串里包含双引号,就把整个整个字符串放在单引号里; 如果字符串包含单引号,就把整个字符串放在双引号里;

   var mood = "don't ask";

//如果想在上面这条语句种使用单引号,就必须保证“n”和“t”之间的单引号能被当成真个字符串的一部分。这种情况下真个单引号需要被看成一个普通字符,而不是真个字符串的结束标志,这种情况我们需要对这个字符进行转义。在JavaScript里用反斜杠进行转义:

   var mood = "don\'t ask";

    * 类似的,如果想用双引号来包住一个本身就包含双引号的字符串,就必须用反斜杠对字符串中的双引号进行转义:

   var height = "aboout 5'10\" tall";
 ---------------------------------------分割线----------------------------------------------------------

//2. 数组

//JavaScript中,数组可以用关键字Array声明。声明数组的同时还可以指定数组初始元素个数,也就是数组的长度:

var beatles = Array(4);

//向数组中添加元素叫做填充

array[index] = element;

//字面量初始化

var beatles = ["John","Paul","George","Ringo"];

//对象

对象时自包含的数据集合,包含在对象里的数据可以通过两种形式访问-属性(property)和方法(method):
[X] 属性时隶属于某个特定对象的变量
[X] 方法是只有某个特定对象的变量
对象就是由一些属性和方法组合在一起而构成的一个数据实体

JavaScript语言里的对象可以分为三种类型;
[X] 用户自定义对象:由程序员自行传教的对象。
[X] 内建对象:内建对象在JavaScript语言里的对象,如ArrayMathDate等;
[X] 宿主对象:由浏览器提供的对象

五、变量的作用域

  1. 全局变量(global varable)可以在脚本中的任何位置被引用。(ps:全局变量的作用域就是整个脚本)
  2. 局部变量(local variable)只存在于声明她的那个函数内部。(ps:局部变量的作用域仅限于某个特定的函数)

    var 关键字明确的为函数变量设定作用域

    • 如果在某个函数中使用了var,那个变量就将被视为一个局部变量,它只存在整个函数的上下文中。 反之如果没有使用var,那么变量就将被视为一个全局变量。

    • 在定义一个函数时,我们一定要把他的内部变量全部都明确的声明为局部变量。

六、最佳实践

  • 质疑一切

如果要使用JavaScript就要确认,这么做会对用户的浏览体验产生怎么样的影响?
如果用户的浏览器不支持JavaScript怎么办

  • 平稳退化
  • 结构样式分离

文档结构和文档样式的分离可以确保网页都能平稳退化。具备CSS支持的浏览器固然可以把网页呈现的美轮美奂,不支持或禁用了CSS功能的浏览器同样可以把网页的内容按照正常的结构显示出来。

  • 渐进增强

所谓渐进增强就是用一些额外的信息去包裹原始数据。按照“渐进增强”原则创建出来的网页(如果不是“全部”的话)都符合“平稳退化”原则;

  • 向后兼容
  • 对象检测
//针对这一问题的最简单的解决方案是,检测浏览器对JavaScript的支持程度
//这种解决方案很容易实现:只要把某个方法打包在一个if语句里,就可以个根据这条if语句的条件表达式的求值结果是true还是false来决定应该采取怎样的行动。这种检测成为对象检测
ifmethod{
statement;
}
//在对象检测时,一定删掉方法名后面的圆括号,如果不删掉,测试的将是方法的结果,无论方法是否存在:
function myFunction(){
  if(document.getElementById){
    statements using getElementById
  }
}
  • 浏览器嗅探技术
  • 性能考虑

尽量少访问DOM和尽量减少标记

访问DOM的方式对脚本性能会产生非常大的影响。
示例代码:

if(document.getElementsByTagName("a").length > 0){
  var links = document.getElmentsByTagName("a"){
   for (var i=0;i<links.length; i++){
       //对每个链接做点处理
     }
  }
}

//首先,它取得了所有<a>元素,然后检查它们个数是不是大于0:
 if(document.getElementsByTagName("a").length>0){
//然后,如果大于0,它会再次取得所有的<a>元素,循环遍历这些元素并应用某些操作;
   var links = document.getElementByTagName("a");
   for (var i=0; i<links.length;i++){
//虽然这段代码可以运行,但它不能保持最优的性能。不管什么时候,只要查询DOM中的某些元素,浏览器都会搜索整个DOM树,从中查找可能匹配的元素。这段代码居然使用了两次getElementByTagName方法去执行相同的操作,浪费了一次搜索。更好的办法时把第一次搜索到的结果保存在一个变量中,然后在循环里重用该结果比如
     var Links  = document.getElementsByTagName("a");
     if(links.length > 0){
       for(var i=0; i<links.length;i++){
        //对每个链接做点处理  
       }  
     }
  • 合并和放置脚本
包含脚本的最佳方式就是使用外部文件,因为外部文件和标记能清晰的分离开,而且浏览器也能对站点中的多个页面重用缓存过的相同脚本。
不过类似下面这种情况也不要出现:

<script scr="functionA.js"></script>
<script scr="functionB.js"></script>
<script scr="functionC.js"></script>
<script scr="functionD.js"></script>

推荐做法就是把functionA.js functionB.js functionC.js functionD合并到一个脚本文件中;
这一就可以减少加载页面时发送的请求数量。而减少请求数量通常都是在性能优化时首先要考虑的。脚本在标签中的位置对页面的初次加载时间也有很大影响。
把所有<script>标签都放在文档的末尾,</body>标记之前,就可以让页面变得更快。
  • 压缩脚本

所谓压缩脚本,指的就是脚本文件中不必要的字节,如空格和注释,统统删除,从而达到“压缩”文件的目的;

六、共享onload事件

网页加载完毕时会触发一个onload事件,这个事件与window对象相关联。
window.onload = func;
这样并不是很完美,如果我有funcA funcB。如果想让他们俩都在页面加载时得到执行,如果它们逐一绑定到onload事件上,它们当中将只有最后那个才会被实际执行:
window.onload = funcA;
window.onload = funcB;
还有一个解决方法就是
window.onload = function(){
  funcA();
  funcB();
}
它确实能很好的工作-在需要绑定的函数不是很多的场合,这应该时最简单的解决方案了。

下面这个弹性最佳的解决方案。不管你打算在页面结束后执行多少个函数,它都应付字符。
[X] 把现有的window.onload事件处理函数的值存入变量oldonload
[X] 如果在这个梳理函数上还没有绑定任何函数,就像平时那样把新函数添加给它
[X] 如果在这个处理函数上已经绑定了一些函数,就把新函数追加到现有指令末尾;
function addLoadEvent(func){
  var oldOnload =  window.onload;
  if (typeof window.onload != 'function' ){
      window.onload = func;
   }else{
     window.onload = function(){
      oldOnload();
      func();
    }
  }
}

七、动态创建标记

* document.write

document 对象的write方法可以方便快捷的把字符串插入到文档中。
例如:document.write("<p>This is inserted.</p>")
缺点:它违背了“行为应该与表现分离”,避免使用document;

* innerHTML属性

现如今所有的浏览器几乎都支持属性innerHTML,这个属性并不是W3C DOM标准的组成部分。它会返回一段HTML代码

* innerHTML属性可以用来读、写某给定元素里的HTML内容
* innerHTML属性无细节可言。想要获得细节,就必须使用DOM方法和属性。标准化的DOM像手术刀一样精细,innder属性就像一把大锤那样粗放。
* 需要将一大段HTML内容插入网页时,innderHTML属性更适用。它支持读写;
* 一旦使用了innerHTML属性,他的全部内容将都被替换
* innerHTML不会返回任何对刚插入的内容的引用
* innerHTML属性要比document.write()方法更指定推荐。使用innderHTML属性,你就可以把JavaScript代码从标记中分离出来。用不着再标记的<body>部分插入<script>标签

八、DOM方法

  • createElement方法
//创建一个新元素
document.createElement(nodeName);
//例如:创建一个p元素
var pTag = document.createElement("p");
  • appendChild方法
//把新创建的节点插入某个文档的节点树;
parent.appendChild(child);
//例如:
var para = document.creatElement("p");
testDiv.appendChild(para);
  • createTextNode方法
//创建文本节点
document.creatTextNode(text);
//例如:创建一个"Hello world"的文本节点
var text = document.createTextNode("Hello world");
para.appendChild(text);


//完整代码
window.onload = function(){
   var para = document.createElement("p");
   var txt  = document.createTextNode("Hello world");
   para.appendChild(txt);
   var testDiv = document.getElementById("testDiv");
   textDiv.appendChild(para);
}
  • insertBefore()方法

    在已有元素前插入一个新元素
    调用此方法,你必须高速它三件事
    (1)新元素:你想插入的元素(newElment)
    (2)目标元素:你想把这个新元素插入到哪个元素(targetElement)之前
    (3)父元素:目标元素的父元素(parentElement)
    下面是这个方法的调用语法

parentElement.insetBefore(newElement,targetElement);

在已有元素后面加入一个元素

这个方法js并没有给我们实现我们就要自己实现了

function insertAfter(newElement,targetElement){
  var parent = targetElement.parentNode;
  if (parent.lastChild == targetElement){
     parent.appendChild(newElement);  
   }else{
     parent.insertBefore(newElement, targetElement.nextSibling);
   }
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值