1.dom对象的innerText和innerHTML有什么区别?
- innerText是一个可写属性。将写入的内容转换成字符串,即使写入的内容是标签,如写入
<p>xxxxxx</p>
也是当成字符串对待。也能返回元素内包含的文本内容,在多层次的时候会按照元素由浅到深的顺序拼接其内容。需要注意的是,并不是单纯的拼接标签内的文本,如下面的例子,拼接的结果并不是“AABBCCDDEEFF”。
<div id="box">AA
<p>BB
<span>CC
<span>DD</span>
</span>
</p>
<p>EE
<span>FF
</span>
</p>
</div>
var box=document.getElementById("box");
console.log(box.innerText);
console.log(box.innerText.length)
var arr=box.innerText.split("");
console.log(arr);
chrome,opera下运行结果,长度18:
(chrome浏览器下,块级标签的开始和结束标签都会产生换行,这里表现为第一个<p>
、第一个</p>
和第二个<p>
产生了换行,第二个</p>
没产生换行是因为后面已经没有元素了;BB、CC和EE后面有空白节点,因而各产生一个空字符,FF后面也有空白节点而没产生空字符是因为<span>FF </span>
后面没有兄弟元素内部也没有子元素)
FireFox下运行结果,长度19:
IE7下运行,长度22。这里不一一截图了。
若想获得字符串“AABBCCDDEEFF”,可以通过innerHTML配合正则表达式来获取。
- innerHTML属性作用和innerText类似,但是不是返回元素的文本内容,而是返回元素的HTML结构,在写入的时候也会自动构建DOM。接上面的例子,运行如下JS代码;
var box=document.getElementById("box");
console.log(box.innerHTML); //返回元素HTML结构
var str=box.innerHTML.replace(/<.+?>|\s*/gim,'');
console.log(str); //返回字符串“AABBCCDDEEFF”
运行结果:
2.elem.children和elem.childNodes的区别?
- elem.children:返回给定元素节点的子节点构成的集合,该集合只包含元素节点。
- elem.childNodes:返回给定元素节点的子节点构成的集合,包含元素节点(nodeType为1)、文本节点(nodeType为3)、注释(nodeType为8)
<ul>
<li>li1</li>
<!-- 这是注释 -->
<li>li2</li>
<li>li3</li>
</ul>
var ul=document.getElementsByTagName("ul")[0];
var childrenNum=console.log(ul.children.length); //3
var childNodesNum=console.log(ul.childNodes.length); //9
3.查询元素有几种常见的方法?
- (1)getElementById( )
返回匹配指定ID属性的元素节点。如果没有发现匹配的节点,则返回null。只能在document对象上调用。
<div id="box">xxx</div>
<script >
var box=document.getElementById("box");
console.log(box); //<div id="box">xxx</div>
var box2=document.getElementById("box2");
console.log(box2); //null
</script>
- (2)getElementsByClassName( )
返回一个类似数组的对象,包括了所有class名字符合指定条件的元素,找不到返回一个空的类数组对象。不仅可以在document对象上调用,也可以在任何元素节点上调用。
<div id="box" class="mybox">
<div class="mybox">xxx</div>
<div class="mybox">xxx</div>
</div>
<div class="mybox">xxx</div>
var box=document.getElementById("box");
var myboxs=box.getElementsByClassName("mybox"); //在获取的box节点上使用
console.log(myboxs.length); //2
- (3)getElementsByTagName( )
和getElementByClassName( )
类似, 返回的是指定标签的元素的类数组对象,不仅可以在document对象上调用,也可以在任何元素节点上调用。 - (4)getElementsByName( )
用于选择拥有name属性的HTML元素,与getElementById() 方法相似,只能在document对象上调用,但是它查询元素的 name 属性,而不是 id 属性 。 返回一个类数组对象,找不到返回一个空的类数组对象。
<a name="ele" href="#"></a>
<input name="ele">
<img name="ele" src="">
<script >
var eles=document.getElementsByName("ele");
console.log(eles.length); //3
var Eles=document.getElementsByName("Ele");
console.log(Eles.length); //0,找不到,返回空数组
</script>
- (5)querySelector( )
返回匹配指定的CSS选择器的元素节点,可以在任意节点上调用。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null。浏览器支持情况:IE8及以上。 - 获取文档中第一个
<p>
元素:
document.querySelector("p");
- 获取文档中 class="example" 的第一个元素:
document.querySelector(".example");
- 获取文档中 class="example" 的第一个
<p>
元素:
document.querySelector("p.example");
- 获取文档中有 "target" 属性的第一个
<a>
元素:
document.querySelector("a[target]");
- (6)querySelectorAll( )
querySelectorAll方法返回匹配指定的CSS选择器的所有节点,可以在任意节点上调用。没找到返回空的类数组对象。 - (7)elementFromPoint()
elementFromPoint方法返回位于页面指定位置的元素。
var element = document.elementFromPoint(x, y);
上面代码中,elementFromPoint方法的参数x和y,分别是相对于当前窗口左上角的横坐标和纵坐标,单位是CSS像素。elementFromPoint方法返回位于这个位置的DOM元素,如果该元素不可返回(比如文本框的滚动条),则返回它的父元素(比如文本框)。如果坐标值无意义(比如负值),则返回null。
4.如何创建一个元素?如何给元素设置属性?元素的添加、删除?
- 通过
document.createElement( )
来创建一个元素 - 通过
appendChild( )
或insertBefore( )
把创建的元素插入到相应位置。 - 通过
removeChild( )
删除节点或replaceChild( )
替换节点 - 通过
setAttribute( )
方法给元素设置属性, 当然,也可以直接ele.style.color="red"
这种方式设置。
综合看下面的例子:
var body=document.body;
var ul=document.createElement("ul"); //创建ul标签
ul.setAttribute("style","background-color:#ddd");
for(var i=0; i<3; i++){
newnode=document.createElement("li");
newnode.innerHTML="li"+(i+1);
newnode.style.backgroundColor="#369145"; //注意,这种设置属性的方法属性名称要写成驼峰式
ul.appendChild(newnode); //将li标签依次插入到ul内部的最后面
}
body.appendChild(ul); //将ul标签添加到body中
nodes=ul.children;
var node4=document.createElement("li");
node4.setAttribute("onclick","javascript:alert('1')"); //给li4设置click事件
node4.innerHTML="li"+(i+1);
ul.insertBefore(node4,nodes[0]); //将node4插入到指定位置
ul.removeChild(nodes[1]); //删除li1
var p=document.createElement("p");
p.innerHTML="一个段落";
ul.replaceChild(p,ul.lastChild); //将ul的最后一个子元素替换成p标签
5.DOM0 级事件和DOM2级在事件监听使用方式上有什么区别?
-
DOM0 级事件
DOM0 级事件处理程序不能添加多个事件处理程序,前面的会被后面的覆盖,有两种使用方式:
(1).HTML内联方式
<input type="button" value="Click Here" onclick="alert('Clicked!');" />
或:
<input type="button" value="Click Here" onclick="showMessage();" />
(2).JavaScript指定事件处理程序
通过JS指定事件处理程序的传统方法,将一个方法赋值给一个事件处理程序属性进行事件监听。
若想删除事件处理程序,只需把元素的onclick属性赋为null即可。
var btn = document.getElementById('btn');
btn.onclick = function showMessage() {
alert(1);
};
// onmouseover事件覆盖了前面的onclick事件,onclick事件不生效
btn.onmouseover = function showMessage() {
alert(2);
};
-
DOM2 级事件
DOM2级事件定义了两个方法用来添加和移除事件处理程序:addEventListener()和removeEventListener()。 - addEventListener():可以为元素添加多个事件处理程序,而且可以是同一事件类型,不同效果叠加,触发时会按照添加顺序依次调用先后执行。
- removeEventListener():用于移除由 addEventListener() 方法添加的事件句柄,不能移除匿名添加的函数。
两种方法都都接受三个参数:
1.事件类型
2.事件处理方法
3.布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false(默认是false),则是在事件冒泡阶段处理。
var hander1=function show1(){
alert(1)
}
var hander2=function show2(){
alert(2)
}
var hander3=function show3(){
alert(3)
}
var li1=document.getElementsByClassName("li1")[0];
li1.addEventListener("click",hander1,true); //alert1
li1.addEventListener("click",hander2,true); // 再次单击alert2
li1.addEventListener("mouseout",hander3,true); //光标离开该元素,alert3
6.attachEvent与addEventListener的区别?
1.参数个数不相同,addEventListener有三个参数,attachEvent只有两个,.attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段);
btn.addEventListener('click', function(){ }, true);
btn.attachEvent('onclick', function(){ });
2.第一个参数意义不同, addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)
3.事件处理程序的作用域不相同,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window,看如下例子:
<div id="box1">box1box1box1</div>
var hander=function showMes(){
alert(this.id)
}
var box1=document.getElementById("box1");
box1.addEventListener("click",hander); //box1
IE下:
<div id="box2">box2box1box2</div>
var hander=function showMes(){
alert(this.id)
}
var box2=document.getElementById("box2");
box2.addEventListener("click",hander); //undefined
4.为一个事件添加多个事件处理程序时,执行顺序不同,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了)
7.解释IE事件冒泡和DOM2事件传播机制?
- IE的只支持事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素
- DOM2事件传播机制:DOM2级事件规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段。可以通过设置addEventListener的第三个参数来决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理。
8.如何阻止事件冒泡? 如何阻止默认事件?
- 如何阻止事件冒泡
function stopPropagation(e) {
if (e.stopPropagation)
e.stopPropagation(); //其它浏览器
else
e.cancelBubble = true; //针对IE
}
- 如何阻止默认事件
function preventDefault(e) {
if (e.preventDefault)
e.preventDefault(); //其它浏览器
else
e.returnValue = false; //针对IE
}
综合看下面的例子:
<div id="outer">outer
<div id="inner"><a href="http://www.baidu.com">百度</a>inner</div>
</div>
<script>
var handler=function (){
alert(this.id)
}
var outer=document.getElementById("outer");
var inner=document.getElementById("inner");
outer.addEventListener("click",handler);
inner.addEventListener("click",stopPropagation); //#inner设置阻止事件冒泡,所以#outer不会alert"outer"
inner.addEventListener("click",preventDefault); //#inner设置阻止默认事件,所以a链接不会跳转
inner.addEventListener("click",handler); //alert "inner"
</script>
代码题
1.有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容
<ul class="ct">
<li>这里是</li>
<li>饥人谷</li>
<li>前端6班</li>
</ul>
<script>
var lis=document.getElementsByClassName("ct")[0].children;
var hander=function (){
console.log(this.innerText);
}
for (var i=0; i<lis.length; i++){
lis[i].addEventListener("click",hander)
}
</script>
2.补全代码,要求:当点击按钮开头添加
时在 < li > 这里是 < /li >
元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加
时在< li >前端6班< /li >
后添加用户输入的非空字符串.当点击每一个元素li时控制台展示该元素的文本内容。
<ul class="ct">
<li>这里是</li>
<li>饥人谷</li>
<li>前端6班</li>
</ul>
<input class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
<script>
var ul=document.getElementsByClassName("ct")[0];
var btnToStart=document.getElementById("btn-add-start");
var btnToEnd=document.getElementById("btn-add-end");
var ipt=document.getElementsByClassName("ipt-add-content")[0];
ul.addEventListener("click",function(e){ //当点击每一个元素li时控制台展示该元素的文本内容
console.log(e.target.innerText);
})
btnToStart.addEventListener("click",function(){ //前面添加新元素
var newli=document.createElement("li");
newli.innerHTML=ipt.value;
ul.insertBefore(newli,ul.children[0])
});
btnToEnd.addEventListener("click",function(){ //后面添加新元素
var newli=document.createElement("li");
newli.innerHTML=ipt.value;
ul.appendChild(newli)
});
</script>
3.补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片。
<ul class="ct">
<li data-img="1.png">鼠标放置查看图片1</li>
<li data-img="2.png">鼠标放置查看图片2</li>
<li data-img="3.png">鼠标放置查看图片3</li>
</ul>
<div class="img-preview">
</div>
<script>
var ul=document.getElementsByClassName("ct")[0];
var container=document.getElementsByClassName("img-preview")[0];
// 方法一:事件代理
// 注意:方法一不能使用mouseenter事件,因为事件是父元素代理,鼠标穿过其子元素时不会触发mouseenter事件,而父元素上又没有data-img属性,所以获取不到图片
// 使用mouseover,当鼠标从标签左侧离开标签时,会发现也出现了获取不到图片的情况,也是因为ul上没有data-img属性
ul.addEventListener("mouseover",function(e){
var dataImg=e.target.getAttribute("data-img");
container.innerHTML="![]("+dataImg+")";
})
// 方法二:使用for循环
//因为事件绑定在li标签上,所以,这里使用mouseover,mouseenter效果一样
// var lis=ul.children;
// for (var i=0; i<lis.length; i++){
// lis[i].addEventListener("mouseenter",function(){
// var dataImg=this.getAttribute("data-img");
// container.innerHTML="![]("+dataImg+")";
// })
// }
</script>
4.实现如下图Tab切换的功能
JS代码:
<script type="text/javascript">
var lis=document.getElementsByClassName("nav")[0].children;
var contents=document.getElementById("wrap").getElementsByTagName("div");
for (var i=0; i<lis.length; i++){
lis[i].index=i;
lis[i].addEventListener("click",function(){
for( var i=0; i<lis.length; i++ ){
lis[i].className="";
}
for(var j=0; j<contents.length; j++){
contents[j].className="hide";
}
this.className="active";
contents[this.index].className="show";
})
}
</script>