Dom、事件

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>

JS Bin链接

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>

JS Bin链接

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>

JS Bin链接

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>

JS Bin链接

5.实现下图的模态框功能

JS Bin链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容