22.Dom、事件

问答

1、dom对象的innerText和innerHTML有什么区别?

  • innerText属性
    ①innerText是一个可写属性,返回元素内包含的文本内容,在多层次的时候会按照由浅到深的顺序拼接其内容;
    ②当写入新内容时会覆盖掉其内部原来所有内容,此时输入的内容为文本格式,即使有HTML标签也会转义成文本;
  • innerHTML属性
    ①innerHTML属性返回元素的HTML结构。它是一个可写的属性,在写入的时候也会自动构建DOM。也就是它不仅获取文本内容还能获取html标签
    ②当写入新内容时也会覆盖掉其内部内容,当有HTML标签时会当成HTML标签处理。
    例如:
  <div id="ct">
      <div>hello jirengu<a href="#">百度</a></div>
  </div>

  <script>
     var ct=document.getElementById('ct');
  </script>

打印结果:


Paste_Image.png

2.elem.children和elem.childNodes的区别?

elem.children和elem.childNodes都是返回元素的直接子元素
区别在于:
elem.children返回的是所有标签的元素节点的集合;
elem.childNodes包括当前节点的所有子节点的集合。除了HTML元素节点,该属性返回的还包括Text节点和Comment节点。其中文本节点包括:空格、换行符和制表符等。

<div id="parent">
        <div class="child">
            <a href="http://www.baidu.com">百度链接</a>
        </div>
        <div>fasdfasdf</div>
        <div>fasdfasdf</div>
        <div>fasdfasdf</div>
</div>

<script>
        var elem=document.getElementById("parent");
</script>
Paste_Image.png

3.查询元素有几种常见的方法?

常见的方法:
getElementById()、getElementsByClassName()、getElementsByTagName()、getElementsByName()、querySelector()、querySelectorAll()

①getElementById()返回匹配指定ID属性的元素节点。如果没有发现匹配的节点,则返回null。注意:如果有几个相同id名,只返回第一个。

<div id="ct">
        <div class="child">hello</div>
</div>
<div id="ct">world!</div>

<script>
        var ct=document.getElementById('ct');
</script>
Paste_Image.png

②getElementsByClassName()方法返回一个类似数组的对象(HTMLCollection类型的对象),包括了所有class名字符合指定条件的元素,元素的变化实时反映在返回结果中。
这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。
注意:这个方法的参数可以是多个空格分隔的class名字,返回同时具有这些节点的元素。

    <div id="ct">
        <div class="child">hello</div>
        <p class="child">好好学习,天天向上<span class="child">学习是一种习惯</span><a href="#" class="child">baidu</a></p>
        <p class="sibling">进度太慢,心里很着急</p>
    </div>
    <div class="sibling neighbor">fasdfa</div>

    <script>
            document.getElementsByClassName('child');
            document.getElementsByClassName("sibling");
            document.getElementsByClassName('sibling neighbor')
            var ct = document.getElementById('ct');
                ct.getElementsByClassName('sibling');
    </script>
Paste_Image.png

③getElementsByTagName()方法返回所有指定标签的元素。返回值是一个HTMLCollection对象(类似数组),任何元素的变化会实时反映在返回结果中。
这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。

   <div id="ct">
        <div class="child">hello</div>
        <p class="child">好好学习,天天向上<span class="child">学习是一种习惯</span><a href="#" class="child">baidu</a></p>
        <p class="sibling">进度太慢,心里很着急</p>
    </div>
    <div class="sibling neighbor">fasdfa</div>

    <script>
            document.getElementsByTagName('p');
    </script>
Paste_Image.png

④getElementsByName方法用于选择拥有name属性的HTML元素,比如form、img、frame、embed和object,返回一个NodeList格式的对象,不会实时反映元素的变化。

    <div id="ct">
        <div class="child">hello</div>
        <p class="child">好好学习,天天向上<span class="child">学习是一种习惯</span><a href="#" class="child">baidu</a></p>
        <p class="sibling">进度太慢,心里很着急</p>
    </div>
    <div class="sibling neighbor">fasdfa</div>
    <form name="submit">
        <input type="text" name="性别">
    </form>

    <script>
            document.getElementsByName('submit');
    </script>
Paste_Image.png

⑤querySelector方法返回匹配指定的CSS选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null。

    <div id="ct">
        <div class="child">hello</div>
        <p class="child">好好学习,天天向上<span class="child">学习是一种习惯</span><a href="#" class="child">baidu</a></p>
        <p class="sibling">进度太慢,心里很着急</p>
    </div>
    <div class="sibling neighbor">fasdfa</div>
    <form name="submit">
        <input type="text" name="性别">
    </form>

    <script>
        document.querySelector('#ct');
        document.querySelector('.child');
        document.querySelector('form[name]');
    </script>
Paste_Image.png

⑥querySelectorAll方法返回匹配指定的CSS选择器的所有节点,返回的是NodeList类型的对象。NodeList对象不是动态集合,所以元素节点的变化无法实时反映在返回结果中。


Paste_Image.png

4.如何创建一个元素?如何给元素设置属性?

①创建一个元素可以用createElement()方法:

var newDiv = document.createElement("div");
var a = document.creatElement("a");

②给元素设置属性可以用setAttribute()方法:

//element.setAttribute("属性名"," 值')
var p = document.querySelector('p');
p.setAttribute('class','text');

③createTextNode()方法用来生成文本节点,参数为所要生成的文本节点的内容。

var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");

5.元素的添加、删除?

添加元素的方法有:
①appendChild()是在调用该方法的元素内添加新元素。新元素是作为子元素被添加的,且是添加在元素内最后的位置。

var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.appendChild(newContent);

②insertBefore()也是在调用该方法的元素内添加新元素。但该方法接收两个参数,一个是被添加的元素,另一个是被“替位”的子元素。新元素会插入在旧子元素的位置之前。

target.insertBefore(newChild,existingChild)
//newChild作为target的子节点插入到existingChild子节点之前

删除元素方法有:
removeChild()能删除指定的元素

parentNode.removeChild(childNode);

替换元素方法有:
replaceChild()接受两个参数:要插入的元素和要替换的元素

var btn1 = document.getElementById("btn1");
var btn3 = document.createElement("button");
btn3.id = "btn3";btn3.innerText = "新按钮";
c1.replaceChild(btn3, btn1);

举例说明:

    <div id="ct">
        <div class="red">红色1</div>
    </div>

    <script>
        //这里是末尾添加appendchild
        var ct = document.getElementById('ct');
        var blue = document.createElement('div');
        blue.className="blue";
        blue.innerText="蓝色2";
        ct.appendChild(blue);

        //这里是插入insertBefore
        var red = document.getElementsByClassName('red')[0];
        /*注意得到的class是数组,要转换成对象*/
        var yellow = document.createElement('div');
        yellow.className="yellow";
        yellow.innerText="黄色3";
        ct.insertBefore(yellow,red);

        //这里是删除removeChild
        ct.removeChild(red);

        //这里面是替换replaceChild
        var green = document.createElement('div');
        green.className="green";
        green.innerText="绿色4";
        ct.replaceChild(green,yellow);

    </script>

6.DOM0事件和DOM2级在事件监听使用方式上有什么区别?

DOM0级事件就是将一个函数赋值给一个事件处理程序属性。
②它的一个事件处理程序只能对应一个事件处理程序,也就是如果对同一事件,后面的处理程序会覆盖前面的.。

方法一:
<a href="#" id="test" onclick="console.log(1);console.log(2);">
   <button type="button">点击我</button>
</a>

方法二:
<script>
    var a = document.getElementById('test');            
    a.onclick = function(){
       console.log('3');
    } 
               
    a.onclick = function(){
         console.log('4');
    }
</script>
删除DOM0事件处理程序,只要将对应事件属性设为null即可,a.onclick = null;

//方法一是把onclick写在元素的标签内的,点击按钮,console中会打印出1和2。方法二是先获取元素,再绑定事件的,注意此处第二个onclick会覆盖第一个onclick的事件处理程序,同时也会覆盖行内的onclick。因此点击按钮,只会打印出4。

①** DOM2级事件处理方式指定了添加事件处理程序和删除事件处理程序的方法,addEventListener和removeEventListener**。
②它的一个事件可以添加多个事件处理程序(可以写多个函数),而不会被后面的所覆盖,同时也不会覆盖DOM0级事件。
③它可以选择在捕获阶段还是冒泡阶段处理程序。
④IE9之前不支持DOM2级事件,而DOM0则跨浏览器且无兼容问题;

 // addEventListener(eventName,func,isPuhuo);  
 // removeEventListener(eventName,func,isPuhuo);

<a href="#" id="test" onclick="console.log(1);console.log(2);"> 
    <button   type="button">点击我</button></a>
<script>
    a.addEventListener('click',function(){
         console.log('我是DOM2级事件1');
    });
    a.addEventListener('click',function(){
         console.log('我是DOM2级事件2');
    });
</script>
//输出的结果是: 1, 2 ,我是DOM2级事件1, 我是DOM2级事件2
```
**所有的DOM节点都包含这两个方法(demo0和domo2),并且接受3个参数:** 
1.事件类型(例如click、mouseover等) 
2.事件处理方法(可写匿名函数,也可写有名函数) 
3.布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理(默认为false,即为在冒泡阶段处理) 

**举例说明:**
```
<a href="#" id="test" onclick="console.log(1);console.log(2);">
   <button type="button">点击我</button>
</a>

<script>
    a.onclick = function(){
       console.log('3'); //会覆盖标签内的DOM0级事件
    };

    var b = function(){
       console.log('我是DOM2级事件b');
    };

   var c = function(){
       console.log('我是DOM2级事件c');
   };

   a.addEventListener('click',b,false);
   a.addEventListener('click',c,true); //在捕获阶段就执行了,因此最早被执行
</script>
//输出的结果是:我是DOM2级事件c ,3, 我是DOM2级事件b 
```

### 7.attachEvent与addEventListener的区别?
①**参数个数不相同**,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)
②**第一个参数意义不同**,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)
③**事件处理程序的作用域不相同**,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window
④**两者为一个事件添加多个事件处理程序时,执行顺序不同:**attachEvent()添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了);而addEventListener()添加多个事件处理程序时是按添加的先后顺序执行
④**支持的浏览器不同:**addEventListener()是W3C标准,支持Chrome、firefox等主流浏览器。attachEvent()非W3C标准,且只支持IE浏览器,别的浏览器不支持。 
```
//判断浏览器是否有该方法:
var btn = getElementById('btn');
if(btn.addEventListener){...} //若有该方法,则会执行函数内语句;若无该方法,则不执行
```

### 8.解释IE事件冒泡和DOM2事件传播机制?
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/2438058-6e20e5c99793fa2e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**IE事件冒泡:**事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)
**所有浏览器都支持事件冒泡,IE只支持事件冒泡,不支持事件捕获。**

**DOM2事件传播机制:**
DOM2模型中,事件的传播分为三个阶段: 
1.事件捕获(capturing phase).事件被从document一直向下传播到目标元素,在这过程中,依次检查经过的节点是否注册了该事件的监听函数(此处要求addEventListener()第三个参数为true),若有则执行。
2.事件处理(target phase).事件到达目标元素,执行目标元素的事件处理函数。 
3.事件冒泡(bubbling phase).事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数(要求addEventListener()的第三个参数为空或者false),若有则执行。
注意,所有的事件都会经历事件捕获阶段,但是只有部分事件会经历事件冒泡,例如submit就不会被事件冒泡。

### 9.如何阻止事件冒泡? 如何阻止默认事件?
IE中的事件对象是window.event ;其他浏览器中必须通过参数把event传过来,比如通过函数的参数传递event对象。
**注意:**event == window.event,所有对象都是window对象的属性,所以不加window浏览器都能认出来。

**阻止事件冒泡:**
**IE浏览器:**将cancelBubble属性设为true可取消冒泡(默认为false)
**其他主流浏览器:**使用stopPropagation()方法可取消事件冒泡,使用event对象在处理事件函数中调用
```
//方法一
function stopPropagation(e){
     var e = window.event||e;
     if(document.all){    //这里判断是否是IE浏览器
                e.cancleBubble = true;
     }else{
                e.stopPropagation();
      }
}

//方法二
function stopBubble(e){
       if(e && e.stopPropagation){ 
                e.stopPropagation();
       }else{
             window.event.cancelBubble = true;
       }
}
```
**阻止默认事件:**
**IE浏览器:**将returnValue属性值设为false可取消事件的默认行为(默认为true),event对象在函数中调用;
**其他主流浏览器:**使用preventDefault()方法可取消事件的默认行为
例如```<a>```标签如果有href属性,点击则会自动跳转。如果取消该事件的默认行为,则不会进行跳转
注意,使用preventDefault的前提是:cancelable属性为true。
```
//方法一
function preventDefaultAction(e){
     var e = window.event||event;
     if(document.all){
             e.returnValue = false;
     }else{
             e.preventDefault();
     }
}

//方法二 
function stopPreventDafaultAction(e){
     if(e && e.preventDeafult){
              e.preventDeafult();
     }else{
             window.event.returnValue = false;
    }
}
```
**举例说明:**
```
    <div id="ct">
        <a class="btn" href="http://www.baidu.com">百度</a>
    </div>
    
    //DOM事件对象
    <script>
        var ct=document.querySelector('#ct');
        var btn=document.querySelector('.btn');

        btn.addEventListener('click',function(event){
            console.log('事件1',event);
            event.preventDefault(); //取消事件默认行为
            event.stopPropagation(); //取消事件冒泡
        });
        ct.addEventListener('click',function(){
            console.log('事件2',event)
            event.preventDefault();
        });


        //IE事件对象
        btn.attachEvent('onclick',function(){
            console.log("事件3",event);
            event.returnValue=false;//取消事件默认行为
            event.cancelBubble=true;//取消事件冒泡
        });
        ct.attachEvent('onclick',function(){
            console.log("事件4",event);
        });
    </script>
```
**老师我有一个问题就是上面的例子DOM事件对象中ct的event不是参数,但是直接写到事件处理函数里面也可以打印出来事件对象,跟视频上讲的和网上查的不一样?**

****
## 代码部分
### 1.有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容
```
<ul class="ct"> 
    <li>这里是</li> 
    <li>杭州</li> 
    <li>西湖</li>
</ul>
<script>
    //todo ...
</script>
```
方法1:事件代理
```
    <ul class="ct">
        <li>这里是</li>
        <li>杭州</li>
        <li>西湖</li>
    </ul>
    
    <script>
        var ct=document.querySelector('.ct');
        ct.addEventListener('click',function(e){
            console.log(e.target.innerHTML);
        });
    </script>
```
[demo](http://js.jirengu.com/gemiyotulo/1/edit?html,js,console,output)

方法2:直接绑定在元素上,用遍历的方法
```
      <ul class="ct">
         <li>这里是</li>
         <li>杭州</li>
         <li>西湖</li>
      </ul>
    
    <script>
        var ct=document.querySelectorAll('li');
        for(var i=0;i<ct.length;i++){
            ct[i].addEventListener('click',function(){
                console.log(this.innerHTML);
            });
        };
        
    </script>
```
[demo](http://js.jirengu.com/gemiyotulo/1/edit?html,js,console,output)

### 2.补全代码,要求:
 1. 当点击按钮```开头添加时```在```<li>这里是</li>```元素前添加一个新元素,                                                                                                                   内容为用户输入的非空字符串;当点击``结尾添加时``在```<li>前端6班</li>```后添加用户输入的非空字符串.
 2.当点击每一个元素```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>
```
```
    <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 ct=document.getElementsByClassName('ct')[0],
            start=document.getElementById('btn-add-start'),
            end=document.getElementById('btn-add-end');

        //这里是事件代理使新添加的节点打印出来
        ct.addEventListener('click',function(e){
                console.log(e.target.innerText)
        })

        start.addEventListener('click',function(){
            //注意这里要点击下去之后才得到输入内容,不能写在外面
            var content=document.getElementsByClassName('ipt-add-content')[0].value;
            if(/\S+/.test(content)){
                var newLi=document.createElement('li');
                newLi.innerText=content;
                ct.insertBefore(newLi,ct.firstChild);
            }else{
                alert('请输入非空字符');
            }
        });

        end.addEventListener('click',function(){
            var content=document.getElementsByClassName('ipt-add-content')[0].value;
            if(/\S+/.test(content)){
                var newLi=document.createElement('li');
                newLi.innerText=content;
                ct.appendChild(newLi);
            }else{
                alert('请输入非空字符');
            }
        });

    </script>
```
[demo](http://js.jirengu.com/gemiyotulo/1/edit?html,js,console,output)

### 3.补全代码,要求:当鼠标放置在`i`元素上,会在```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>
```
```
//方法一:用appendChild,注意需要用innerText事先清空preview内的内容
    <ul class="ct">
        <li data-img="http://pic.58pic.com/58pic/13/72/07/55Z58PICKka_1024.jpg">鼠标放置查看图片1</li>
        <li data-img="http://img3.3lian.com/2013/s2/37/d/28.jpg">鼠标放置查看图片2</li>
        <li data-img="http://image.cnsc8.com/tupian_201410/Big_Pic/lXrknEGPnt.jpg">鼠标放置查看图片3</li>
    </ul>
    <div class="img-preview"></div>
    

    <script>
        var ct=document.querySelector('.ct');
        var pre=document.querySelector('.img-preview');
        ct.addEventListener('mouseover',function(event){
            var newPic=document.createElement('img');
            pre.innerText='';  //清空preview内的内容
            newPic.setAttribute('src',event.target.getAttribute('data-img'))
            pre.appendChild(newPic);
        });
    </script>

```
[demo](http://js.jirengu.com/gemiyotulo/1/edit?html,js,output)

```
//方法二、用innerHTML,注意双引号、单引号的用法
    <ul class="ct">
        <li data-img="http://pic.58pic.com/58pic/13/72/07/55Z58PICKka_1024.jpg">鼠标放置查看图片1</li>
        <li data-img="http://img3.3lian.com/2013/s2/37/d/28.jpg">鼠标放置查看图片2</li>
        <li data-img="http://image.cnsc8.com/tupian_201410/Big_Pic/lXrknEGPnt.jpg">鼠标放置查看图片3</li>
    </ul>
    <div class="img-preview"></div>
    
    <script>
        var ct=document.querySelector('.ct');
        var pre=document.querySelector('.img-preview');

        var hover=function(event){
            pre.innerHTML='<img src=" '+event.target.getAttribute('data-img')+' ">'

        }
        ct.addEventListener('mouseover',hover);
    </script>
```
[demo](http://js.jirengu.com/caqamoqeyi/1/edit?html,js,output)

### 4.实现如下图Tab切换的功能
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/2438058-69d3816693f338b5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

```
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>tab 切换</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>
    *{
        box-sizing:border-box;
    }
    body,ul,li{
        margin:0px;
        padding:0px;
        
    }
    ul:after{
        content: "";
        display: block;
        clear: both;
    }
    li{
        border:1px solid;
        list-style: none;
        width: 200px;
        height: 30px;
        text-align: center;
        line-height: 30px;
        float: left;
        cursor: pointer;
    }
    div{
        border: 1px solid;
        width: 600px;
        height: 300px;
        display: none;
        padding: 20px;
    }

    .active1{
        background:#EEE;
    }
    .active2{
        display: block;
    }

</style>

</head>
<body>
    <ul id="tab">
        <li class="active1">tab1</li>
        <li>tab2</li>
        <li>tab3</li>
    </ul>
    <div class="content active2">内容1</div>
    <div class="content">内容2</div>
    <div class="content">内容3</div>

    <script>
        function hasClass(ele,cls){
            var reg=new RegExp('\\b'+cls+'\\b');
            return !!ele.className.match(reg);
        };

        function addClass(ele,cls){
            if(hasClass(ele,cls)){
                return
            }else{
                
                return ele.className=ele.className+' '+cls;
            }
        };

        function removeClass(ele,cls){
            if(hasClass(ele,cls)){
                var reg=new RegExp('\\b'+cls+'\\b');
                return ele.className=ele.className.replace(reg,'')
            }else{
                return;
            }
        };
        //上面的将原有的,添加,删除的三个函数进行封装

        function indexOf(ele){
            var tab=document.querySelector('#tab');
            for(var i=0;i<tab.children.length;i++){
                if(ele.target==tab.children[i]){
                    return i;
                }
            }
        };
        //这里是获取数组里面点击li的下标

        function toggleContent(ele){
            var index=indexOf(ele);
            //这是找出点击li的下标
            var content=document.querySelectorAll('.content');
            for(var i=0;i<content.length;i++){
                removeClass(content[i],'active2');
            }
            //通过遍历content数组,删除里面的active2
            addClass(content[index],'active2')
            //这是给点击li相对应的content添加active2
        }
        //这里是切换内容,获取点击li的下标,通过下标找出相对应的内容

        var tab=document.querySelector('#tab');
        function toggleTab(ele){
            var children=tab.children;
            if(hasClass(ele.target,'active1')){
                return;
            }else{
                for(var i=0;i<children.length;i++){
                    removeClass(children[i],'active1');
                }
                addClass(ele.target,'active1');
            }
        }
        //这里是切换tab,跟上面差不多

        tab.addEventListener('click',toggleTab);
        tab.addEventListener('click',toggleContent);
     //这里用了事件代理tab
```
[demo](http://js.jirengu.com/wujaluboka/1/edit?html,css,js,output)

### 5.实现下图的模态框功能
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/2438058-1470ef12bc4cdb4e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

```
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>modal模态框 原生</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>
    *{
        margin:0px;
        padding: 0px;
    }
    a{
        text-decoration: none;
        color:black;
    }
    .head{
        border-bottom:1px solid #AAA;
        padding:14px;
    }
    .head p{
        float: left;

    }
    .head a{
        float: right;
    }
    .head:after{
        content:"";
        display: block;
        clear:both;
    }
    .hide{
        display: none;
    }
    .show{
        display: block;
    }
    .btn{
        position: absolute;
        left: 50%;
        margin-left: -270px;
        top: 9px;
    }
    .cover{
        width: 600px;
        height: 500px;
        background-color: #000;
        opacity: 0.5;
        position: absolute;
        top: 0;
        left: 50%;
        margin-left: -300px;
    }
    #modal{
        border: 1px solid #CCC;
        width: 300px;
        height: 180px;
        background-color: #FFF;
        border-radius: 4px;
        position: absolute;
        top:160px;
        left: 50%;
        margin-left: -150px;
    }

    .content{
        padding: 15px;
        line-height: 2;
    }
    .footer{
        float:right;
        padding: 12px;
    }
</style>

</head>
<body>
    <div class="btn">
        <button id="btnChild">点我</button>
    </div>
    <div class="cover hide"></div>
    <div id="modal" class="hide">
        <div class="head">
            <p>我是标题</p>
            <a class="close" href="#">X</a>
        </div>
        <div class="content">
            <p>我是内容一</p>
            <p>我是内容二</p>
        </div>
        <div class="footer">
            <button class="btn-cancel">取消</button>
            <button class="btn-confirm">确定</button>
        </div>
    </div>
        

    <script>
        var btnChild=document.querySelector('#btnChild');
        var modal=document.querySelector('#modal');
        var cover=document.querySelector('.cover');
        var close=document.querySelector('.close');
        var btnCancel=document.querySelector('.btn-cancel');
        var btnConfirm=document.querySelector('.btn-confirm');

        function hasClass(ele,cls){
            var reg=new RegExp('\\b'+cls+'\\b','g');
            return !!ele.className.match(reg);

        }

        function addClass(ele,cls){
            if(hasClass(ele,cls)){
                return;
            }else{
                ele.className=ele.className+" "+cls;
            } 
        }

        function removeClass(ele,cls){
            if(hasClass(ele,cls)){
                var reg=new RegExp('\\b'+cls+'\\b','g');
                return ele.className=ele.className.replace(reg,'');
            }
        }

        function showModal(ele){
            removeClass(modal,'hide');
            removeClass(cover,'hide');
            addClass(modal,'show');
            addClass(cover,'show');
        }

        function hideModal(ele){
            removeClass(modal,'show');
            removeClass(cover,'show');
            addClass(modal,'hide');
            addClass(cover,'hide');
        }

        btnChild.addEventListener('click',showModal);
        cover.addEventListener('click',hideModal);
        close.addEventListener('click',hideModal);
        btnCancel.addEventListener('click',hideModal);
        btnConfirm.addEventListener('click',hideModal);
        
    </script>
</body>
</html>

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

推荐阅读更多精彩内容