问答
一、dom对象的innerText和innerHTML有什么区别?
- innerText
innerText是一个可写属性,返回元素内包含的文本内容,在多层次的时候会按照元素由浅到深的顺序拼接其内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>innerText</title>
</head>
<body>
<div>
<p>
123
<span>456</span>
</p>
</div>
</body>
</html>
外层div的innerText返回内容是 "123456"
-
innerHTML
innerHTML和innerText的作用类似,但是它不是返回元素的文本内容,而是返回元素的HTML结构。
二、elem.children和elem.childNodes的区别?
- elem.children
elem.children是一个只读属性,对象类型为HTMLCollection
,返回一个包含当前元素的子元素的集合。非元素的部分,比如空格、换行、或者单纯的文字不返回(文本节点以外的其他HTML节点)。 - elem.chilNodes
elem.chilNodes是获取包括文本节点的所有子元素列表(NodeList)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Element</title>
</head>
<body>
<div>
<p id="desp">
<span>1</span>
</p>
<!-- <p class="desp">段落2<span>2</span></p>
<p class="desp">段落3<span>3</span></p> -->
</div>
<script>
var p = document.getElementById('desp');
console.log(p);
console.log(p.children);
console.log(p.children[0]);
console.log(p.childNodes);
console.log(p.childNodes[0]);
</script>
</body>
</html>
一般来说,elem.children更稳妥一些。如上面结果所示,使用elem.chilNodes获取的第一个元素不是span,而是回车符(相当于文本字符)。
三、查询元素有几种常见的方法?
- getElementById()
返回匹配指定ID属性的元素节点,如果没有匹配的节点,则返回null。这是获取元素最快的方法。
var elem = document.getElementById('ct');
- getElementsByClassName()
返回一个类似数组的对象(HTMLCollection类型的对象),包括了所有class名字符合指定条件的元素(搜索范围包括本身),元素的变化实时反映在返回结果中。这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。
var elements = document.getElementsByClassName('desp');
getElementsByClassName方法的参数,可以是多个空格分隔的class名字,返回同时具有这些节点的元素。
var elements = document.getElementsByClassName('test desp');
- getElementsByTagName()
返回所有指定标签的元素(搜索范围包括本身),返回值是一个HTMLCollection对象,也就是说,搜索结果是一个动态集合,任何元素的变化都会实时反映在返回的集合中。这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。注意:此方法会将参数转换为小写后再进行搜索。
var elements = document.getElementsByTagName('p');
- getElementsByName()
返回具有name属性的HTML元素,比如form、img、frame、embed和object,返回NodeList格式的对象,也就是说不会实时的反应元素的变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form name="myForm" action="/test/6.php" method="post">
姓名:<input name="username" type="text" placeholder="用户名" value="hello" maxlength=10 /> <br/>
密码:<input name="pwd" type="text" placeholder="密码" maxlength=10 disabled /> <br/>
性别:<input type="radio" name="sex" value="male" /> 男
<input type="radio" name="sex" value="female" /> 女 <br/>
爱好:<input type="checkbox" name="bike" checked />自行车
<input type="checkbox" name="car" checked />汽车
</form>
<script>
var forms = document.getElementsByName("username");
console.log(forms);
console.log(forms[0].tagName);
</script>
</body>
</html>
注意:在IE浏览器使用这个方法,会将没有name属性、但有同名id属性的元素也返回,所以name和id属性最好设为不一样的值。
- querySelector()
返回匹配指定CSS选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有匹配的节点,则返回null。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="user-panel main">
<input name="login"/>
</div>
<script>
var el = document.querySelector("div.user-panel input[name=login]");
console.log(el);
</script>
</body>
</html>
- querySelectorAll()
返回匹配指定CSS选择器的所有节点,返回的是NodeList类型的对象。
var matches = document.querySelectorAll("div.note, div.alert"); // 返回class属性为note或者alert的div元素
- elementFromPoint()
返回位于页面指定位置的元素。如果该元素不可返回(比如文本框的滚动条),则返回它的父元素;如果坐标无意义,则返回null。
var ele = document.elementFromPoint(x, y); // x,y分别是相对于当前窗口左上角的横坐标和纵坐标,单位是CSS像素。
四、如何创建一个元素?如何给元素设置属性?
1、创建元素
- createElement()
createElement用来生成HTML元素节点,参数为元素的标签名,即元素的tagName属性。如果传入的为大写的标签名,则会被转换为小写。如果参数带有尖括号(即<和>)或者是null,会报错。
var newDiv = document.createElement('div');
- createTextNode()
用来生成文本节点,参数为文本节点的内容。
var newDiv = document.createElement('div');
var newContent = document.createTextNode('我是div');
- createDocumentFragment()
用于生成一个DocumentFragment对象。DocumentFragment可以提供一个缓冲的机制,将DOM节点先放到内存中,当节点都构造完成后,再将DocumentFragment对象添加到页面中,这时所有的节点都会一次渲染出来,这样就能减少浏览器很多的负担,明显的提高页面渲染速度。
var fragment = document.createDocumentFragment();
2、给元素设置属性
setAttribute()可以用来给元素设置属性。
<div id='ct'>Hello</div>
<script>
var el = document.getElementById('ct');
el.setAttribute('myAttribute', 'newVal');
</script>
五、元素的添加、删除?
1、元素的添加
- appendChild()
用于向节点添加最后一个子节点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<ul class="ct">
<li class="item"><span class="s">1</span>1</li>
<li class="item"><span class="s">4</span>4</li>
<li class="item"><span class="s">3</span>3</li>
<li class="item"><span class="s">2</span>2</li>
</ul>
</body>
<script>
var items = document.querySelectorAll('.item');
var itemsArr = [];
for(var i=0;i<items.length;i++)
{
itemsArr.push(items[i]);
}
itemsArr.sort(function(a, b){
return parseInt(a.children[0].innerText) - parseInt(b.children[0].innerText);
})
for(var i=0;i<itemsArr.length;i++)
{
document.querySelector('.ct').appendChild(itemsArr[i]);
}
</script>
</html>
- insertBefore()
在某个元素之前插入元素。
<div id="ct">
<p>1</p>
<p>2</p>
</div>
<script>
var span = document.createElement('span');
var el = document.getElementById('ct');
el.insertBefore(span, el.firstChild); // 在<p>1</p>前插入
</script>
2、元素的删除
removeChild()
六、DOM0 事件和DOM2级在事件监听使用方式上有什么区别?
- DOM0
DOM0级事件处理程序是将一个函数赋值给一个事件处理程序属性,而通过将事件处理程序设置为null删除绑定在元素上的事件处理程序。无法给一个事件添加多个事件处理程序,后面的程序会覆盖前面的程序。
<input id='btn' type='button' value='click me...' />
<script type="text/javascript">
var btnClick = document.getElementById('btn');
// 添加事件处理程序
btnClick.onclick = function () {
alert (this.id);
};
// 删除事件处理程序
btnClick.onclick = null;
</script>
- DOM2
DOM2级事件定义了两个方法用于添加和删除事件处理程序的操作:addEventListener
和removeEventListener
。所有DOM节点都包含这两个方法,它们接受三个参数:事件类型、事件处理方法、布尔参数(true,表示在捕获阶段调用事件处理程序;false:表示在事件冒泡阶段处理)。
<input id='btn' typ='button' value='click me...' />
<script type="text/javascript">
var btnClick = document.querySelector('#btn');
btnClick.addEventListener('click', function(){
alert(this.id);
}, false);
// 可以为click事件添加多个处理程序
btnClick.addEventListener('click', function(){
alert('Hello');
}, false);
</script>
通过addEventListener添加的事件处理程序只能通过removeListener移除,移除时参数与添加的时候相同,这就意味着刚才我们添加的匿名函数无法移除。因为匿名函数虽然方法体一样,但是句柄却不相同。所以可以如下实现:
<input id="btn" type="button" value="Click Here" />
<script type="text/javascript">
var btnClick = document.getElementById('btn');
var handler=function() {
alert(this.id);
}
btnClick.addEventListener('click', handler, false);
btnClick.removeEventListener('click', handler, false);
</script>
七、attachEvent与addEventListener的区别?
IE不支持addEventListener和removeListener,而是实现了两个类似的方法:attachEvent和detachEvent。
attachEvent与addEventListener的区别:
-
参数个数不同
addEventListener有三个参数,attachEvent只有两个。attachEvent添加事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理。 -
第一个参数意义不同
addEventListener第一个参数是事件类型(click),而attachEvent第一个参数是事件处理函数名称(onclick)。 -
事件处理程序的作用域不相同
addEventListener作用域是元素本身,this指的是触发的元素。而attachEvent事件处理程序会在全局变量内运行,事件处理程序会在全局变量内运行。 -
为一个事件添加多个事件处理程序时,执行顺序不同
addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律。
八、解释IE事件冒泡和DOM2事件传播机制?
- IE事件冒泡
事件由最具体的元素接收,然后逐级向上传播到较为不具体的元素。 - DOM2事件传播机制
DOM2事件规定事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的是事件捕获阶段,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段。
九、如何阻止事件冒泡? 如何阻止默认事件?
- 阻止事件冒泡
当bubbles为true时,可以通过stopPropagation()方法阻止事件冒泡。 - 阻止默认事件
当cancelable为true时,可以通过preventDefault()方法阻止默认事件。
<div id="ct">
<button id="btn">点我</button>
<a id='link' target="_blank" href='www.baidu.com'>百度</a>
</div>
<script type="text/javascript">
var wrap = document.querySelector('#ct');
var btn = document.querySelector('#btn');
var link = document.querySelector('#link');
wrap.addEventListener('click', function(e){
console.log(this.id);
}, false);
btn.addEventListener('click', function(e){
console.log(this.id);
e.stopPropagation();
}, false);
link.addEventListener('click', function(e){
console.log(this.id);
e.preventDefault();
}, false);
</script>
代码
一、有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容
<ul class="ct">
<li>苹果</li>
<li>橘子</li>
<li>香蕉</li>
</ul>
<script>
//todo ...
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>one</title>
</head>
<body>
<ul class="ct">
<li>苹果</li>
<li>橘子</li>
<li>香蕉</li>
</ul>
<script>
var ct = document.getElementsByClassName('ct')[0];
ct.addEventListener('click', function(e){
console.log(e.target.innerText);
}, false);
</script>
</body>
</html>
二、补全代码,要求:
- 当点击按钮开头添加时在
<li>苹果</li>
元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加时在<li>香蕉</li>
后添加用户输入的非空字符串. - 当点击每一个元素
li
时控制台展示该元素的文本内容。
<ul class="ct">
<li>苹果</li>
<li>橘子</li>
<li>香蕉</li>
</ul>
<input class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
<script>
//todo ...
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>second</title>
</head>
<body>
<ul class="ct">
<li>苹果</li>
<li>橘子</li>
<li>香蕉</li>
</ul>
<input class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
<script>
// 获取input的输入值
var value;
var input = document.getElementsByClassName('ipt-add-content')[0];
input.addEventListener('change', function(e){
value = e.target.value;
}, false);
document.body.addEventListener('click', function(e){
// 增加元素
var ct = document.getElementsByClassName('ct')[0];
var li = document.createElement('li');
var content = document.createTextNode(value);
li.appendChild(content);
if(e.target.id == 'btn-add-start')
{
var addStart = document.getElementById('btn-add-start');
var eleStart = ct.children[0];
if(!value)
{
alert('输入内容不能为空');
return;
}
ct.insertBefore(li, eleStart);
}
if(e.target.id == 'btn-add-end')
{
if(!value)
{
alert('输入内容不能为空');
return;
}
ct.appendChild(li);
}
console.log(e);
// 点击li打印文本内容
if(e.target.tagName.toLowerCase() == 'li')
{
console.log(e.target.innerText);
}
}, false);
</script>
</body>
</html>
三、补全代码,要求:当鼠标放置在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>
//todo ...
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>third</title>
</head>
<body>
<ul class="ct">
<li data-img="http://ww3.sinaimg.cn/bmiddle/68bf4cd7ly1fb9899g6bij226k3vj7wp.jpg">鼠标放置查看图片1</li>
<li data-img="http://ww2.sinaimg.cn/bmiddle/68bf4cd7ly1fb98bn69t6j21111trqva.jpg">鼠标放置查看图片2</li>
<li data-img="http://ww3.sinaimg.cn/bmiddle/68bf4cd7ly1fb98bzvmzbj21ww2pfe82.jpg">鼠标放置查看图片3</li>
</ul>
<div class="img-preview"></div>
<script>
var ct = document.querySelector('.ct');
console.log(ct);
var preview = document.querySelector('.img-preview');
ct.addEventListener('mouseover', function(e){
var url = e.target.getAttribute('data-img');
preview.innerHTML = `<img src= "${url}" />`;
}, false);
</script>
</body>
</html>
四、实现如下图Tab切换的功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>fourth</title>
<style>
html, body, ul, li{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
a{
text-decoration: none;
color: black;
}
.ct{
height: 210px;
width: 600px;
border: 2px solid #ccc;
font-weight: 600;
}
.nav > li{
float: left;
width: 200px;
line-height: 30px;
border-bottom: 2px solid #ccc;
text-align: center;
}
.nav>li:hover{
background: #ededed;
}
</style>
</head>
<body>
<div class='ct'>
<ul class='nav'>
<li><a href='#'>tab1</a></li>
<li><a href="#">tab2</a></li>
<li><a href="#">tab3</a></li>
</ul>
<div class='content'>内容1</div>
</div>
<script>
var tab = document.querySelector('.ct');
var contentTag = document.querySelector('.content');
tab.addEventListener('click', function(e){
var value = e.target.innerText;
switch(value)
{
case 'tab1':
contentTag.innerText = '内容1';
break;
case 'tab2':
contentTag.innerText = '内容2';
break;
case 'tab3':
contentTag.innerText = '内容3';
break;
}
}, false);
</script>
</body>
</html>
五、实现下图的模态框功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>fifth</title>
<style>
*{
margin: 0px;
padding: 0px;
}
a{
text-decoration: none;
color: black;
}
hr{
border-color: #fff;
}
.clearFix:after{
content: '';
display: block;
clear: both;
}
.cover{
background: black;
position: fixed;
top: 0;
left: 0;
opacity: 0.3;
width: 100vw;
height: 100vh;
display: none;
}
.modal{
position: absolute;
top: 50%;
left: 50%;
width: 400px;
transform: translate(-50%, -50%); //绝对定位+transform, 只需设置宽度,高度自适应
z-index: 1;
border-radius: 4px;
font-size: 18px;
padding: 0 3px;
background: #fff;
display: none;
}
.header{
height: 40px;
line-height: 40px;
}
.header>h3{
float: left;
}
.close{
float: right;
}
.content{
margin: 10px 0px;
line-height: 36px;
}
.footer{
float: right;
height: 40px;
line-height: 40px;
}
.footer>a{
}
</style>
</head>
<body>
<button class='showModal'>点我1</button>
<div class='cover'></div>
<div class='modal'>
<div class='header clearFix'>
<h3>我是标题1</h3>
<a class='close' href='#'>×</a>
</div>
<hr>
<div class='content'>
<p>我是内容1</p>
<p>我是内容1</p>
</div>
<hr>
<div class='footer clearFix'>
<a class='cancel' href='#'>取消</a>
<a class='confirm' href='#'>确定</a>
</div>
</div>
<script>
var btn = document.querySelector('.showModal'),
modal = document.querySelector('.modal'),
cover = document.querySelector('.cover'),
close = document.querySelector('.close'),
cancel = document.querySelector('.cancel');
function showModal() {
modal.style.display = 'block';
cover.style.display = 'block';
}
function cancelModal() {
modal.style.display = 'none';
cover.style.display = 'none';
}
btn.addEventListener('click', function(e){
showModal();
}, false);
cover.addEventListener('click', function(e){
cancelModal();
}, false);
close.addEventListener('click', function(e){
cancelModal();
}, false);
cancel.addEventListener('click', function(e){
cancelModal();
}, false);
</script>
</body>
</html>
由于预览好像有问题就放在js bin上面了。