一、问答
1. dom对象的innerText
和innerHTML
有什么区别?
-
innerHTML
: 也就是从对象的起始位置到终止位置的全部内容,包括Html标签。 -
innerHTML
: 从起始位置到终止位置的内容, 但它去除Html标签 。
2. elem.children
和elem.childNodes
的区别?
-
elem.children
:它返回指定元素的子元素集合, 不会返回TextNode。用的比较多
-elem.childNodes
: 它返回指定元素的子元素集合,包括HTML节点,所有属性,文本。
3. 查询元素有几种常见的方法?
- 原生JS获取元素的方法
(1).通过顶层document节点获取:- document.getElementById(elementId):该方法通过节点的ID,可以准确获得需要的元素,是比较简单快捷的方法。如果页面上含有多个相同id的节点,那么只返回第一个节点。
- document.getElementsByName(elementName):用来选择一些具有name属性的html元素,比如form、img等,返回一个储存对应类名的类数组对象,要用arr[i] 来使用,只有 document
能使用 - document.getElementsByTagName(tagName):该方法是通过节点的Tag获取节点,同样该方法也是返回一个数组
- document.getElementsByClassName(className):通过类名来选择元素,返回一个储存对应类名的类数组对象
- querySelector():使用css选择器语法来选中目标元素,会返回匹配到的元素节点如果有多个满足条件的元素节点将只返回第一个
- querySelectorAll() :与querrSelector类似,返回所有满足条件的元素节点,是一个类数组对象
4. 如何创建一个元素?如何给元素设置属性?
1.如何创建一个元素
-
document.createElement()
: 用来生成HTML元素节点;
-createTextNode()
:createTextNode方法用来生成文本节点,参数为所要生成的文本节点的内容。
-createDocumentFragment()
:createDocumentFragment方法生成一个DocumentFragment对象。
- 你
- 是
- 谁
- 在
- 干
2.如何给元素设置属性
- HTML元素对象有一个
attributes
属性,返回一个类似数组的动态对象,成员是该元素标签的所有属性节点对象,属性的实时变化都会反映在这个节点对象上。其他类型的节点对象,虽然也有attributes
属性,但是返回的都是null
,因此可以把这个属性视为元素对象独有的。 - 常用有两种方法:第一种是直接用HTML标签对象进行读写操作,第二种是用setAttribute()方法进行读写;
5. 元素的添加、删除?
- 添加元素的方法:
- appendChild() :在元素末尾添加元素
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.appendChild(newContent);
- insertBefore():在某个元素之前插入元素
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.insertBefore(newContent, newDiv.firstChild);
- replaceChild():replaceChild()接受两个参数:要插入的元素和要替换的元素
newDiv.replaceChild(newElement, oldElement);```
- 删除元素的方法:
- removeChild()
parentNode.removeChild(childNode);
![节点对象的方法](http://upload-images.jianshu.io/upload_images/2775927-59814a76c7241b25.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
###6. DOM0 事件和DOM2级在事件监听使用方式上有什么区别?
- 概念:事件是某些动作发生时产生的信号。JavaScript能够感知这些信号,因此能够编写代码来响应这些信号,也就是响应这些事件。而响应某个事件的函数就叫做**事件处理程序(或事件侦听器)**。事件处理程序的名字以on开头,所以click点击事件的事件处理程序就是onclick,load事件的事件处理程序就是onload等等。
- DOM0级事件处理程序:
因为在HTML代码中直接指定事件处理程序存在一些缺陷,所以人们转而使用JavaScript来指定事件处理程序。通过JavaScript来指定事件处理程序的方式就是将一个函数赋值给一个事件处理属性。
在DOM0级事件处理程序中,要使用JavaScript来指定事件处理程序,首先需要获取操作对象的引用。每一个元素对象都有自己的事件处理属性,例如onclick
,将这些属性的值设置为一个函数,就可以指定事件处理程序了。例如:
使用DOM0级方法指定的事件处理程序被认为是元素的方法。这时候的事件处理程序是在元素的作用域中运行的,也就是说,在事件处理程序中,this
引用就是这个元素对象。例如:
我们可以在上事件处理程序中使用this
关键字来获取元素的所有属性和方法。以这种方式添加的事件处理程序会在[事件流](http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201512012851.html)的冒泡阶段被处理。例如使用下面的代码可以查看事件冒泡的情况。
下面是控制台中输出的结果:
![firefox-event-bubbling.jpg](http://upload-images.jianshu.io/upload_images/2775927-64a7f8e287ba6de5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
从控制台中的输出结果可以看出,由上到下的顺序为child→parent→body→html,说明事件最先发生在按钮(child)上面,然后逐级往上冒泡。
DOM0事件处理程序会产生事件冒泡。如果要取消事件冒泡,可以使用event.stopPropagation()方法,但是IE浏览器不支持这个方法,在IE中,取消事件冒泡的方法为:event.cancleBubble = true。
//取消事件冒泡
event.stopPropagation(); //DOM方法
event.cancleBubble = true; //IE的方法
另外要提的一点是DOM0事件处理程序不支持事件捕获。
我们也可以删除通过DOM0级方法指定的事件处理程序,只要将事件处理程序属性的值设置为null即可。
btn.onclick = null;
使用DOM0级事件处理程序最大的问题是事件会被覆盖。来看下面的例子:
在上面的代码中,通过按钮的引用对象为按钮添加了3个事件处理函数,那么现在的问题是哪一个事件处理程序会被执行?答案是第三个事件处理程序会被执行,控制台中会输出“event-three”。这是因为btn.onclick
实际上就像一个指针,在执行第一个事件处理程序时它指向了内存中的一个引用,执行第二个事件处理程序时它又会指向另一个内存的引用,最终会指向第3个事件处理函数的内存引用。
- DOM2级事件处理程序
由于DOM0级事件处理程序会产生事件冒泡和事件覆盖等问题,W3C组织制定了“DOM2级事件处理程序”。“DOM2级事件处理程序”定义了2个方法,用于处理指定和删除事件处理程序的操作,这2个方法是:```addEventListener```和```removeEventListener```。所有的DOM节点中都包含这两个方法,这些方法接收3个参数:**要处理的事件名称**、**作为事件处理程序的函数**和**一个布尔值**。布尔值参数如果设置为**true**,表示在**捕获阶段调用事件处理程序**,如果设置为**false**,表示在事件**冒泡阶段调用事件处理程序**。
如果要在一个按钮上添加DOM2级事件处理程序,可以使用下面的代码:
上面的代码为按钮添加了一个DOM2级事件处理程序,事件名称是click,对应DOM0级的onclick属性。因为最后一个参数为false,所以这个事件会在冒泡阶段被触发。
和DOM0级事件处理程序相同,DOM2级事件处理程序也会依附在元素的作用域中运行。
使用DOM2级事件处理程序就可以避免DOM0级事件处理程序的事件覆盖问题。例如下面的例子:
查看控制台我们会发现,3个事件都会被执行,控制台中依次打印出:“event-one”、“event-two”和“event-three”。
接下来,我们可以来看一下事件捕获的情况。[上一篇文章](http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201512012851.html)只是介绍了事件捕获,并没有举一个具体的例子。下面我们在DOM2级事件处理程序中来查看事件捕获的过程。代码如下:
由于在上面的事件处理程序中,第3个参数被设置为true
,表示在捕获阶段调用事件处理程序。在Firefox浏览器的控制台中得到下面的结果:
![firefox-dom2-event.jpg](http://upload-images.jianshu.io/upload_images/2775927-44e32d854f93b284.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
从控制台的结果中可以看到,事件源是按钮,事件对象从上往下分别为:
→→→。
通过addEventListener()方法添加的事件处理程序只能通过removeEventListener()方法来移除。移除时传入的参数和添加事件处理程序时的参数一样。注意:通过addEventListener()方法添加的匿名函数将无法移除。下面是一个移除DOM2级事件处理程序的例子:
var btn = document.getElementById("btn");
btn.addEventListener("click",function(){
console.info(this.id);
},false);
......
btn.removeEventListener("click",function(){/函数在此处没有用/},false);
传入removeEventListener()中的事件处理函数必须与addEventListener()中的事件处理函数相同,例如:
var fn = function(){
console.info(this.id);
}
var btn = document.getElementById("btn");
btn.addEventListener("click",fn,false);
......
btn.removeEventListener("click",fn,false);
在多数情况下,都是将事件处理程序添加到事件流的事件冒泡阶段,这样可以最大限度的兼容各种浏览器。最好只在事件到达目标之前截获它的时候将事件处理程序添加到事件捕获阶段。
###7. ```attachEvent```与```addEventListener```的区别?
- 在添加事件处理程序事addEventListener和attachEvent主要有几个区别:
(1). **参数个数不相同**,这个最直观,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)
(2). **第一个参数意义不同**,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)
(3). **事件处理程序的作用域不相同**,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window,所以刚才例子才会返回undefined,而不是元素id
(4). **为一个事件添加多个事件处理程序时,执行顺序不同**,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器
###8. 解释IE事件冒泡和DOM2事件传播机制?
- 事件冒泡:
IE的事件流叫做事件冒泡(event bubbling),它是指事件最初由最具体的元素接收,然后逐级向上传播到较为不具体的节点。例如有下面的HTML代码:
如果你点击了页面中的按钮,那么事件将按照如下的顺序进行传播: