Dom 文档对象模型


< DOM >
    1.文档:一个页面就是一个文档,DOM中使用document表示
    2.元素:页面中的标签都是元素,DOM中使用element表示
    3.节点:网页中所有的内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
    DOM把以上内容都看做是对象

    1.获取页面元素:
        (1)根据ID获取: document.getElementById()
            // 1.因为文档页面是从上往下加载的,先得有标签, 所以script写到标签的下面
            // 2.get 获得  element 元素  by 通过  驼峰命名法
            // 3.参数 id是大小写敏感的字符串
            // 4.返回的是一个元素对象
            // 5.console.dir(timer)   可以打印返回的元素对象,更好的查看里面的属性和方法

                <div id="time">2019-9-9</div>
                <script>
                    var time = document.getElementById('time');    // id 以字符串形式书写
                    console.log(time);    // <div id="timer">
                    console.log(typeof timer);    // object
                    console.dir(timer);    // 可以打印返回的元素对象,更好的查看里面的属性和方法
                </script>

        (2)根据标签名获取:document.getElementsByTagName()  方法 可以返回带有指定标签名的对象的集合
            // 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储(伪数组:有长度,有索引号,但是没有数组的方法)
            // 2.想要依次打印里面的元素对象,可以采取遍历的方式
            // 3.因为得到的是一个对象的集合,所以想要操作里面的元素就需要遍历
            // 4.得到的元素对象是动态的
            // 5.如果页面中只有一个元素 <li> 返回的还是伪数组的形式
            // 6.如果页面中没有这个元素,返回的是一个空的伪数组  ( length:0 )
                <ul>
                    <li>噢噢噢噢1</li>
                    <li>噢噢噢噢2</li>
                    <li>噢噢噢噢3</li>
                    <li>噢噢噢噢4</li>
                    <li>噢噢噢噢5</li>
                </ul>
                <script>
                    var lis = document.getElementsByTagName('li');
                    console.log(lis);    // HTMLCollection(5){0:li,1:li,2:li,3:li,4:li,length:5}   
                        // lis指所有的<li>
                    console.log(lis[0]);    //  <li>噢噢噢噢1</li>   返回第一个<li>
                    for(var i = 0; i < lis.length ; i++){
                        console.log(lis[i]);     // 遍历所有的 <li>
                    }
                </script>

        (3)指定父元素,获取其子元素  获取某个父元素内部指定标签名的子元素
            // 父元素.getElementsByTagName('');
            // 父元素必须是单个对象(必须指明是哪一个元素对象)获取的时候不包括父元素自己
            例如:获取<ol>下的<li>
                <ul>
                    <li>a</li>
                    <li>b</li>
                    <li>c</li>
                </ul>
                <ol>
                    <li>A</li>
                    <li>B</li>
                    <li>C</li>
                </ol>
                <script>
                    var ol = document.getElementsByTagName('ol');      // 获取所有的<ol>
                    console.log(ol[0].getElementsByTagName('li'));     // HTMLCollection { 0: li, 1: li, 2: li, length: 3 } 获取第一个<ol>下的所有<li>
                </script>

        (4)根据HTML5新增的方法获取
             1.document.getElementsByClassName('类名');     // 根据类名返回元素对象集合
                <div class="box">盒子1</div>
                <div class="box">盒子2</div>
                <div id = "nav">
                    <ul>
                        <li>首页</li>
                        <li>产品</li>
                    </ul>
                </div>
                <script>
                    var boxs = document.getElementsByClassName('box');
                    console.log(boxs);    // HTMLCollection { 0: div.box, 1: div.box, length: 2 }
                </script>

             2.document.querySelector('选择器');    // 根据指定选择器返回第一个元素对象
                <div class="box">盒子1</div>
                <div class="box">盒子2</div>
                <div id = "nav">
                    <ul>
                        <li>首页</li>
                        <li>产品</li>
                    </ul>
                </div>
                <script>
                    var firstBox = document.querySelector('.box');     // 类
                    console.log(firstBox);      // <div class="box">盒子1</div>   // 返回第一个元素对象
                    var nav = document.querySelector('#nav');    // ID
                    console.log(nav);    // <div id="nav">     
                    var li = document.querySelector('li');       // 标签
                    console.log(li);     // <li>首页</li>    
                </script>

            3.document.querySelectorAll('选择器');    // 根据指定选择器返回所有元素对象 (是个集合)
                <div class="box">盒子1</div>
                <div class="box">盒子2</div>
                <script>
                    var allBox = document.querySelectorAll('.box');
                    console.log('allBox');   
                </script>
                
        (5)获取特殊元素
            1.获取<body>元素  document.body        返回的是个元素对象
                var bodyEle = document.body;
                console.log(bodyEle);    // <body>  返回的是一个元素对象
                console.dir(bodyEle);
            2.获取<html>元素  document.documentElement
                var htmlEle = document.documentElement;
                console.log(htmlEle);    //  <html>

    2.事件基础
        触发---响应机制
        事件是由三部分组成: 事件源、 事件类型、 事件处理程序    这三部分也称为事件三要素
            (1)事件源:事件被触发的对象   谁   按钮
            (2)事件类型:如何触发   
                    比如:
                        onclick         鼠标点击左键触发
                        onmouseover     鼠标经过触发
                        onmouseout      鼠标离开触发
                        onfocus         获取鼠标焦点触发
                        onblur          失去鼠标焦点触发
                        onmousemove     鼠标移动触发
                        onmouseup       鼠标弹起触发
                        onmousedown     鼠标按下触发
            (3)事件处理程序:通过一个函数赋值的方式来完成
                <button id = "btn"> 唐伯虎 </button>
                <script>
                    // 1.事件源
                    var btn = document.getElementById('btn');   
                    // 2.事件类型 onclick
                    // 3.事件处理程序  
                    btn.onclick = function(){    
                        alert('点秋香');
                    }
                </script>
        执行事件的步骤:
            (1)获取事件源
            (2)绑定事件
            (3)添加事件处理程序(采取函数赋值的形式)
                <div>ABC</div>
                <script>
                    // 1.获取事件源
                    var div = document.querySelector('div');
                    // 2.绑定事件   div.onclick
                    // 3.添加事件处理程序
                    div.onclick = function(){
                        console.log('我被选中了');
                    }
                </script>

    3.操作元素
        (1)改变元素内容
                (a)element.innerText    // 从其实位置到终止位置,但它不识别html标签,同时空格和换行也会去掉
                    案例:点击按钮显示当前时间
                    <button>显示当前系统时间</button>
                    <div>某个时间</div>
                    <p>123</p>
                    <script>
                        // 当我们点击了按钮,div里面的文字会发生变化
                        // 1. 获取元素
                        var btn = document.querySelector('button');
                        var div = document.querySelector('div');
                        // 2.注册时间
                        btn.onclick = function(){
                            div.innerText = '';
                        }
                        function getDate(){
                            var date = new Date();
                            var year = date.getFullYear();
                            var month = date.getMonth() + 1;
                            var dates = date.getDate();
                            var arr  = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
                            var day = date.getDay();
                            return '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
                        }
                        // 元素可以不用添加事件
                        var p = document.querySelector('p');
                        p.innerHTML = getDate();
                    </script>

                (b)element.innerHTML    // 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
                
                · innerHext 和 innerHTML 的区别
                    // 1.innerText   不识别html标签,非标准
                         innerHTML   可以识别html标签,是W3C标准,常用

                        var div = document.querySelector('div');
                        div.innerText = '<strong>今天是:</strong>2019';     // <strong>今天是:</strong>2019
                        div.innerHTML = '<strong>今天是:</strong>2019';     // 今天是:2019
                    // 2.innerText    去除空格和换行
                         innerHTML    保留空格和换行
                        <p>
                            我是文字
                            <span>123</span>
                        </p>
                        var p = document.querySelector('p');
                        console.log(p.innerText);     // 我是文字 123
                        console.log(p.innerHTML);     //
                                                            我是文字
                                                            <span>123</span>
                                        
                    // 相同点:这两个属性是可读写的,可以获取元素里面的内容

        (2)改变元素属性   元素名.属性名
                <button id="ldh">刘德华</button>
                <button id="zxy">张学友</button>
                <img src="images/ldh.jpg" alt="" title="刘德华">
                <script>
                    // 修改元素属性   src
                    // 1.获取元素
                        var ldh = document.getElementById('ldh');
                        var zxy = document.getElementById('zxy');
                        var img = document.querySelector('img');
                    // 2.注册事件   处理程序
                        zxy.onclick = function(){
                            img.src = 'images/zxy.jpg';
                            img.title = '张学友';
                        }
                        ldh.onclick = function(){
                            img.src = 'images/ldh.jpg';
                            img.title = '刘德华';
                        }
                </script>  
            案例:分时显示不同图片,显示不同问候语
                // 根据不同的时间,页面显示不同的图片,同时显示不同的问候语
                // 如: 上午时间:显示上午好,显示上午图片
                    <img src = "images/sw.jpg" alt="">
                    <div>上午好</div>
                    <script>
                        // 1.获取元素
                        var img = document.querySelector('img');
                        var div = document.querySelector('div');
                        // 2.得到当前的小时数
                        var date = new Date();
                        var h = date.getHours();
                        // 3.判断小时数改变图片和文字信息
                         if(h<12){
                             img.src = 'images/sw.jpg';
                             div.innerHTML = '上午好';
                         }else if (h < 18){
                             img.src = 'images/xw.jpg';
                             div.innerHTML = '下午好';
                         }else{
                             img.src = 'images/ws.jpg';
                             div.innerHTML = '晚上好';
                         }
                    </script>
            
        (3)表单元素的属性操作
            type、 value、 checked、 selected、 disabled
                <button>按钮</button>
                <input type = "text" value="输入内容">
                <script>
                    // 1.获取元素
                    var btn = document.querySelector('button');
                    var input = document.querySelector('input');
                    // 2.注册事件 处理程序
                    btn.onclick = function(){
                        input.value = '被点击了';    // 表单里面的值 文字内容是通过 value 来修改的
                        // 如果想要某个表单被禁用 不能再点击 disabled   
                        // 想要按钮 button 被禁用
                        //btn.disabled = true;    可以使用this代替 效果一样
                        this.disabled = true;    
                        // this 指向的是事件函数的调用者  btn
                    }
                </script>

         案例:仿京东显示密码
            <style>
                .box{
                    position: relative;
                    width: 400px;
                    border-bottom: 1px solid #ccc;
                    margin: 100px auto;
                }
                .box input{
                    height: 30px;
                    width: 370px;
                    border: 0;
                    outline: none;
                }
                .box img{
                    width: 24px;
                    position: absolute;
                    top: 2px;
                    right: 2px;
                }
            </style>
            <body>
                <div class="box">
                    <label for="">
                        <img src="images/eye-close.png" alt="" id="eye">
                    </label>
                    <input type="password" name = "" id="pwd">
                </div>
                <script>
                    // 1.获取元素
                    var eye = document.getElementById('eye');
                    var pwd = document.getElementById('pwd');
                    // 2.绑定事件 处理程序
                    var flag = 0;
                    eye.onclick = function(){
                        // 点击一次之后  flag一定要变化
                        if( flag == 0 ){
                            pwd.type = 'text';
                            eye.src = 'images/open.png';
                            flag = 1;
                        }else{
                            pwd.type = 'password';
                            eye.src = 'images/eye-close.png';
                            flag = 0;
                        }
                    }
                </script>
            </body>

        (4)样式属性操作
            1.element.style      行内样式操作
             注意:// 1.JS里面的样式采取驼峰命名法, 比如:fontSize、 backgroundColor
                  // 2.JS修改 style 样式操作,产生的是行内样式,css权重比较高
                    <style>
                        div{
                            width: 200px;
                            height: 200px;
                            background-color: pink;
                        }
                    </style>
                    <body>
                        <div></div>
                        <script>
                            // 1.获取元素
                            var div = document.querySelector('div');
                            // 2.绑定事件 处理程序
                            div.onclick = function(){
                                this.style.backgroundColor = 'purple';
                                this.style.width = '250px';
                            }
                        </script>
                    </body>
                
             案例:淘宝点击关闭二维码
                // 隐藏:display:none;  显示:display:block;
                <style>
                    .box{
                        position: relative;
                        width: 74px;
                        height: 88px;
                        border: 1px solid #ccc;
                        margin: 100px auto;
                        font-size: 12px;
                        text-align: center;
                        color: #f40;
                        display: block;
                    }
                    .box img{
                        width: 60px;
                        margin-top: 5px;
                    }
                    .close-btn{
                        position: absolute;
                        top:-1px;
                        left: -16px;
                        width: 14px;
                        height: 14px;
                        border: 1px solid #ccc;
                        line-height: 14px;
                        font-family: Arial, Helvetica, sans-serif;
                        cursor: pointer;
                    }
                </style>
                <body>
                    <div class="box">
                        淘宝二维码
                        <img src="images/二维码.png" alt="">
                        <i class="close-btn">X</i>
                    </div>
                    <script>
                        // 1.获取元素
                        var btn = document.querySelector('.close-btn');
                        var box = document.querySelector('.box');
                        // 2.绑定事件 程序处理
                        btn.onclick = function(){
                            box.style.display = 'none';
                        }
                    </script>
                </body>
             案例:循环精灵图背景
             案例:显示隐藏文本框内容
                // 获得焦点:onfocus   失去焦点:onblur
                <style>
                    input{
                        color: #999;
                    }
                </style>
                <body>
                    <input type="text" value="手机">
                    <script>
                        // 1.获取元素
                        var text = document.querySelector('input');
                        // 2.绑定事件 获得焦点事件  onfocus
                        text.onfocus = function(){
                            // console.log('得到了焦点');
                            if(this.value==='手机'){
                                this.value='';
                            }
                            // 获得焦点需要把文本框里面的文字颜色变黑
                            this.style.color = '#333';
                        }
                        // 3.绑定事件 失去焦点   onblur
                        text.οnblur= function(){
                            // console.log('失去了焦点');
                            if(this.value === ''){
                                this.value = '手机';
                            }
                            // 失去焦点需要把文本框里面的文字颜色变浅
                            this.style.color = '#999';
                        }
                    </script>
                
            2.element.className     类名样式操作
                // 可以通过修改元素的className更改元素的样式,适合于样式较多或者功能复杂的情况
                注意:// 1.如果样式修改较多,可以采取操作类名方式更改元素样式
                     // 2.class因为是个保留字,因此使用className来操作元素类名属性
                     // 3.className会直接更改元素的类名,会覆盖原先的类名
                     // 4.如果想要保留原先的类名 如:this.className = 'first change';
                    <style>
                        div{
                            width: 100px;
                            height: 100px;
                            background-color: pink;
                        }
                        .change{
                            background-color: purple;
                            font-size: 25px;
                            margin-top: 50px;
                            color: #fff;
                        }
                    </style>
                    <div class="first">文本</div>
                    <script>
                        // 1.使用 element.style 获得修改元素样式
                        var test = document.querySelector('div');
                        test.onclick = function(){
                            // this.style.backgroundColor = 'purple';
                            // this.style.color = '#fff';
                            // this.style.fontSize = '25px';
                            // this.style.marginTop = '50px';
                            this.className = 'change';
                            // 让当前元素的类名改为 change
                        }
                    </script>
             案例:仿新浪注册页面
                <style>
                    div{
                        width:600px;
                        margin: 100px auto;
                    }
                    .message{
                        display: inline-block;
                        font-size: 12px;
                        color: #999;
                        background: url(images/eye-close.png) no-repeat left center;
                        padding-left: 20px;
                    }
                    .wrong{
                        color: red;
                        background: url(images/open.png);
                    }
                    .right{
                        color: green;
                    }
                </style>
                <div class="register">
                    <input type="password" class="ipt">
                    <p class="message">请输入6~16位密码</p>
                </div>
                <script>
                    // 1.获取元素
                        var ipt = document.querySelector('.ipt');
                        var message = document.querySelector('.message');
                    // 2.注册事件 失去焦点
                        ipt.onblur = function(){
                            // 根据表单里面值的长度 ipt.value.length
                            if(this.value.length < 6 || this.value.length>16){
                                // console.log('cuowu');
                                message.className = 'message wrong';
                                message.innerHTML = '您输入的位数不对';
                            }else{
                                message.className = 'message right';
                                message.innerHTML = '正确';
                            }
                        }
                </script>

        操作元素总结:
            操作元素:
                1.操作元素内容
                    (1)innerText
                    (2)innerHTML
                2.操作常见元素属性
                    src、href、title、alt等
                3.操作表单元素属性
                    type、value、disabled等
                4.操作元素样式属性    
                    (1)element.style
                    (2)className

        (5)排他思想
                // 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
                // 1.所有元素全部清除样式(首先干掉他人)
                // 2.给当前元素设置样式(然后留下我自己)
                // 3.注意顺序不能颠倒,首先干掉其他人,再设置自己
                <button>按钮1</button>
                <button>按钮2</button>
                <button>按钮3</button>
                <button>按钮4</button>
                <button>按钮5</button>
                <script>
                    // 1. 获取所有按钮元素
                    var btns = document.getElementsByTagName('button');
                    // btns 得到的是伪数组 里面的每一个元素 btns[i]
                    for(var i = 0;i<btns.length;i++){
                        btns[i].onclick = function(){
                            // (1)我们先把所有的按钮背景颜色去掉
                            for(var i = 0 ;i<btns.length;i++){
                                btns[i].style.backgroundColor = '';
                            }
                            // (2)然后才让当前的元素换背景颜色
                            this.style.backgroundColor = 'pink';
                        }
                    }
                </script>

        案例:背景换肤
            <ul class="baidu">
                <li><img src="images/1.jpg" alt=""></li>
                <li><img src="images/2.jpg" alt=""></li>
                <li><img src="images/3.jpg" alt=""></li>
                <li><img src="images/4.jpg" alt=""></li>
            </ul>
            <script>
                // 1.获取元素
                var imgs = document.querySelector('.baidu').querySelector('img');
                // 2.循环注册事件
                for(var i = 0;i<imgs.length;i++){
                    imgs[i].onclick = function(){
                        // this.src 就是点击图片的路径
                        this.src;
                        // 把这个路径给body 就可以了
                        document.body.style.backgroundImg = 'url('+this.src+')';
                    }
                }
            </script>

        案例:表格隔行变色
            // 用到鼠标事件: 鼠标经过:onmouseover 鼠标离开:onmouseout
            <table>
                <thead>
                    <tr>
                        <th>代码</th>
                        <th>名称</th>
                        <th>最新公布净值</th>
                        <th>累计净值</th>
                        <th>前单位净值</th>
                        <th>净值增长率</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <th>003526</th>
                        <th>21312312</th>
                        <th>1212313212</th>
                        <th>2123132</th>
                        <th>123123123</th>
                        <th>123123123</th>
                    </tr>
                    <tr>
                        <th>003526</th>
                        <th>21312312</th>
                        <th>1212313212</th>
                        <th>2123132</th>
                        <th>123123123</th>
                        <th>123123123</th>
                    </tr>
                    <tr>
                        <th>003526</th>
                        <th>21312312</th>
                        <th>1212313212</th>
                        <th>2123132</th>
                        <th>123123123</th>
                        <th>123123123</th>
                    </tr>
                </tbody>
            </table>
            <script>
                // 1.获取元素 获取的是tbody 里面所有的行
                var trs = document.querySelector('tbody').querySelectorAll('tr');
                // 2.利用循环绑定事件
                for(var i = 0 ;i<trs.length;i++){
                    // 3.鼠标经过事件 onmouseover
                    trs[i].onmouseover = function(){
                        this.className = 'bg';
                    }
                    // 4.鼠标离开事件 onmouseout
                    trs[i].onmouseout = function(){
                        this.className = '';
                    }
                }
            </script>

        案例:表单全选与取消全选
<div class="wrap">
    <table>
        <thead>
            <tr>
                <th>
                    <input type="checkbox" id="j_cbAll"/>
                </th>
                <th>商品</th>
                <th>价格</th>
            </tr>
        </thead>
        <tbody id="j_tb">
            <tr>
                <td>
                    <input type="checkbox"/>
                </td>
                <td>iphone8</td>
                <td>800</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox"/>
                </td>
                <td>iphone8</td>
                <td>800</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox"/>
                </td>
                <td>iphone8</td>
                <td>800</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox"/>
                </td>
                <td>iphone8</td>
                <td>800</td>
            </tr>
        </tbody>
    </table>
</div>
<script>
    // 1.全选和取消全选做法: 让下面所有复选框的checked属性(选中状态)跟随全选按钮即可
    // 获取元素
    var j_cbAll = document.getElementById('j_cbAll');     // 全选按钮
    var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); // 下面所有的复选框
    // 注册事件
    j_cbAll.onclick = function(){
        // this.checked;      // 可以得到当前复选框的选中状态,如果是true 就是选中,如果是false 就是未选中
        for(var i = 0 ;i<j_tbs.length;i++){
            j_tbs[i].checked = this.checked;     // 全选与取消全选
        }
    }

    // 2.下面复选框需要全部选中,上面全选才能选中做法:给下面所有复选框绑定点击事件,每次点击,都要循环检查这四个小按钮是否全部被选中
    for(var i = 0 ; i<j_tbs.length;i++){
        j_tbs[i].onclick = function(){
            //flag      控制全选按钮是否选中
            var flag = true;
            // 每次点击下面的复选框都要循环检查这四个小按钮是否全部被选中
            for(var i = 0;i<j_tbs.length;i++){
                if(!j_tbs[i].checked){
                    flag = false;
                    break;    // 退出for循环 提高执行效率  因为只要有一个没有选中 剩下的就无需循环
                }
            }
            j_cbAll.checked = flag;
        }
    }
</script>

        (6)获取自定义属性操作
            1.获取元素的属性值
                (1)element.属性
                (2)element.getAttribute('属性')     // attribute 是属性的意思
                区别:element.属性   获取内置属性值(元素本身自带的属性)    如:id、 class
                     element.getAttribute('属性')     主要获得自定义的属性(标准)程序员自定义的属性
            2.设置属性值
                (1)element.属性 = '值'
                (2)element.setAttribute('属性','值')     主要针对于自定义属性
            3.移除属性
                element.removeAttribute('属性');
                    <div id="demo" index = "1"></div>
                        <script>
                            var div = document.querySelector('div');     // demo
                            // 1.获取元素属性值
                            // (1)element.属性      主要用于 内置属性
                            console.log(div.id);
                            // (2)element.getAttribute('属性')      主要用于 自定义属性
                            console.log(div.getAttribute('id'));    // demo
                            console.log(div.getAttribute('index'));    // 1
                            
                            // 2.设置属性值
                            // (1)element.属性='值'
                            div.id = 'text';
                            console.log(div.id);
                            // (2)element.setAttribute('属性','值')
                            div.setAttribute('id','demo');
                            console.log(div.id);
                            div.setAttribute('index',2);
                            console.log(div.getAttribute('index'));
                            div.setAttribute('class','footer');    // class 特殊 这里面写的就是class 不是className

                            // 3.移除属性值
                            div.removeAttribute('index');
                            console.log(div.getAttribute('index'));    // null
                        </script>

        案例:tab栏切换(重点)
<style>
    .tab_list li{
        float: left;
        height: 39px;
        line-height: 39px;
        padding: 0 20px;
        text-align: center;
        cursor: pointer;
    }
    .tab_list::after{
        content: '';
        clear: both;
        display: block;
    }
    .current{
        background-color: #c81623;
        color: #fff;
    }
    .item_info{
        padding: 20px 0 0 20px;
    }
    .item{
        display: none;
    }
</style>
<div class="tab">
    <div class="tab_list">
        <ul>
            <li class="current">商品介绍</li>
            <li>规格与包装</li>
            <li>售后保障</li>
            <li>商品评价</li>
            <li>手机社区</li>
        </ul>
    </div>
    <div class="tab_con">
        <div class="item" style="display: block;">
            商品介绍模块
        </div>
        <div class="item">
            规格与包装模块
        </div>
        <div class="item">
            售后保障模块
        </div>
        <div class="item">
            商品评价模块
        </div>
        <div class="item">
            手机社区装模块
        </div>
    </div>
</div>
<script>
    // 1. 上面的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想)修改类名的方式
    // 获取元素
    var tab_list = document.querySelector('.tab_list');
    var lis = tab_list.querySelectorAll('li');
    var items = document.querySelectorAll('.item');
    // for循环 绑定点击事件
    for(var i = 0 ; i<lis.length; i++){
        // 开始给 五个 li 设置索引号
        lis[i].setAttribute('index',i);
        lis[i].onclick = function(){
            // 干掉所有人  其余的li清除class 这个类
            for(var i = 0;i<lis.length;i++){
                lis[i].className = '';
            }
            // 留下我自己
            this.className = 'current';
            // 2. 下面的显示内容模块
            var index = this.getAttribute('index');
            // 干掉所有人 让其余的item 这些div 隐藏
            for(var i = 0;i<items.length;i++){
                items[i].style.display = 'none';
            }
            // 留下我自己  让对应的item 显示出来
            items[index].style.display = 'block';
        }
    }
</script>

        (7)H5自定义属性
            1.使用自定义属性目的:就是为了保存并使用数据(有些数据可以保存到页面中而不用保存到数据库中)
            2.自定义属性可以通过 getAttribute('属性') 获取
            3.但是有些自定义属性容易引起歧义,很难去判断是元素的内置属性还是自定义属性

            1.设置自定义属性:
                (1)H5规定自定义属性要以 date- 开头作为属性名并赋值
                    如:<div data-index="1"></div
                (2)或者使用JS直接设置
                    如:element.setAttribute('data-index',2)
            2.获取自定义属性
                (1)element.getAttribute('data-index')
                (2)H5新增:element.dataset.index  或者 element.dataset['index']
                    <div getTime="20" data-index="1" data-list-name="andy"></div>
                    <!-- 规范书写 -->
                    <script>
                        var div = document.querySelector('div');
                        console.log(div.getAttribute('getTime'));
                        div.setAttribute('data-time',10);
                        console.log(div.getAttribute('data-time'));
                        console.log(div.getAttribute('data-list-name'));
                        // H5 新增的获取自定义属性的方法  dataset 只能获取data- 开头的
                        // dataset 是一个集合 里面存放了所有以data- 开头的自定义属性
                        console.log(div.dataset);
                        console.log(div.dataset.index);
                        console.log(div.dataset['index']);
                        // 如果自定义属性里面有多个 - 链接的单词,我们获取的时候采取 驼峰命名法
                        console.log(div.dataset.listName);   
                        console.log(div.dataset['listName']);
                    </script>

    4.节点操作
        1.获取元素通常使用两种方式:
            (1)利用DOM提供的方法获取元素
                document.getElementById
                document.getElementsByTagName
                document.querySelector等
                // 逻辑性不强、比较繁琐
            (2)利用节点层级关系获取元素
                // 利用父子兄节点关系获取元素
                // 逻辑性强、但是兼容性稍差
        2.节点概述
            网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示
            DOM树中的所有节点均可通过JS进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除
            一般地,节点至少拥有:nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)这三个基本属性
                元素节点  nodeType 为 1  
                属性节点  nodeType 为 2
                文本节点  nodeType 为 3 (文本节点包括 文字、 空格、 换行等)
        3.节点层级
            利用DOM树 可以把节点划分为不同的层级关系,常见的是父子兄的层级关系
            (1)父级节点: node.parentNode
                // parentNode 属性可返回某节点的父节点 注意是最近的一个父节点
                // 如果指定的节点没有父节点则返回 null
            (2)子节点:  node.childNodes   (包含所有的节点)
                // 返回值里面包含了所有的子节点,包含 元素节点 文本节点等等
                // 如果只想要获得里面的元素节点,则需要专门处理,所以我们一般不提倡使用childNodes
            (3)子元素节点: node.children   (只包含元素节点)
                // node.children 是一个只读属性,只返回所有的子元素节点
            (4)第一个子节点:  node.firstChild
            (5)最后一个子节点:  node.lastChild
            (6)第一个子元素节点:  node.firstElementChild   (ie9以上使用)
            (7)最后一个子元素节点:  node.lastElementChild   (ie9以上使用)
            (8)实际开发的写法:node.children[index]  
                (a)第一个子元素节点:  node.children[0]  
                (b)最后一个子元素节点:  node.children[node.children.length - 1]   
                // 既没有兼容性问题又可以返回特定的子元素

                    <div class="demo">
                        <div class="parent">
                            <div class="son"></div>
                            <div class="xon"></div>
                        </div>
                    </div>
                    <script>
                        // 1.父节点 node.parentNode
                        var son = document.querySelector('.son');
                        // var parent = document.querySelector('.parent');
                        son.parentNode;    // 得到的是离该元素最近的父级节点 如果找不到父节点就返回为 null
                        console.log(son.parentNode);

                        // 2.子节点 node.childNodes
                        var parent = document.querySelector('.parent');
                        parent.childNodes;
                        console.log(parent.childNodes);    
                        console.log(parent.childNodes[0].nodeType);    
                        console.log(parent.childNodes[1].nodeType);    

                        // 3.子元素节点 node.children
                        console.log(parent.children);

                        // 4.第一个子节点 node.firstChild   
                        console.log(parent.firstChild);

                        // 5.最后一个子节点 node.lastChild   
                        console.log(parent.lastChild);

                        // 6.第一子元素节点  node.firstElementChild
                        console.log(parent.firstElementChild);

                        // 7.第一子元素节点  node.firstElementChild
                        console.log(parent.lastElementChild);

                        // 8.实际开发的写法 既没有兼容性问题又可以返回特定的子元素
                        console.log(parent.children[0]);
                        console.log(parent.children[parent.children.length - 1]);
                    </script>

            案例:新浪下拉菜单
                  <style>
                    .nav>li{
                        float: left;
                        margin-right: 100px;
                    }
                    .nav>li>a:hover{
                        background-color: #eee;
                    }
                    .nav ul{
                        display: none;
                        position: absolute;
                        top: 41px;
                        left: 0;
                        width: 100%;
                        border-left:1px solid #fecc5b;
                        border-right: 1px solid #fecc5b;
                    }
                    .nav ul li{
                        border-bottom:1px solid #fecc5b;
                    }
                    .nav ul li a:hover{
                        background-color: #FFF5DA;
                    }
                </style>
                <ul class="nav">
                    <li>
                        <a href="#">111</a>
                        <ul>
                            <li>
                                <a href="">111</a>
                            </li>
                            <li>
                                <a href="">111</a>
                            </li>
                            <li>
                                <a href="">111</a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="#">222</a>
                        <ul>
                            <li>
                                <a href="">222</a>
                            </li>
                            <li>
                                <a href="">222</a>
                            </li>
                            <li>
                                <a href="">222</a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="#">333</a>
                        <ul>
                            <li>
                                <a href="">333</a>
                            </li>
                            <li>
                                <a href="">333</a>
                            </li>
                            <li>
                                <a href="">333</a>
                            </li>
                        </ul>
                    </li>
                </ul>
                <script>
                    // 1.获取元素
                    var nav = document.querySelector('.nav');
                    var lis = nav.children;   // 得到所有子元素节点
                    // 2.循环注册事件
                    for(var i = 0; i<lis.length;i++){
                        lis[i].onmouseover = function(){
                            this.children[1].style.display = 'block';
                        }
                        lis[i].onmouseout = function(){
                            this.children[1].style.display = 'none';
                        }
                    }
                </script>
                
            (9)兄弟节点
                (a)下一个兄弟节点:  node.nextSibling
                    // nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null,也是包含所有的节点
                (b)上一个兄弟节点:  node.previousSibling
                    // previousSibling 返回当前元素的上一个兄弟节点,找不到返回null,包含所有的节点
                (c)下一个兄弟元素节点:  node.nextElementSibling
                    // nextElementSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null
                (d)上一个兄弟元素节点:  node.previousElementSibling
                    // previousElementSibling 返回当前元素的上一个兄弟元素节点,找不到则返回null
                (f)如何解决 nextElementSibling 和 previousElementSibling 的兼容性问题?
                        function getNextElementSibling(element){
                            var el = element;
                            while(el = el.nextSibling){
                                if(el.nodeType === 1){
                                    return el;
                                }
                            }
                            return null;
                        }

        4.创建和添加节点
            创建节点:document.createElement('tagName')
                // document.createElement()方法创建由 tagName 指定的 HTML 元素,
                // 因为这些元素原先不存在是根据我们的需求动态生成的,所以我们也成为动态创建元素节点
            后面追加节点:node.appendChild(child)         
                // 在子元素的后面追加节点  类似于数组中的push  css中的after伪元素
            前面插入节点:node.insertBefore(child,指定元素)
                // 将一个节点添加到父节点的指定子节点前面  类似于css中的before伪元素

                <ul>
                    <li>123</li>
                </ul>
                <script>
                    // 1.创建元素节点    document.createElement('tagName')
                    var li = document.createElement('li');
                    var ul = document.querySelector('ul');
                    // 2.后面追加节点   node.appendChild(child)   node 父级   child 是子级 后面追加元素
                    ul.appendChild(li);
                    // 3.前面插入节点     node.insertBefore(child,指定元素)
                    var lili = document.createElement('li');
                    ul.insertBefore(lili,ul.children[0]);
                </script>

        案例:简单版发布留言
                <textarea name="" id="" cols="30" rows="10"></textarea>
                <button>发布</button>
                <ul>
                </ul>
                <script>
                    // 1.获取元素
                    var btn = document.querySelector('button');
                    var text = document.querySelector('textarea');
                    var ul = document.querySelector('ul');
                    // 2.绑定事件
                    btn.onclick = function(){
                        if(text.value == ''){
                            alert('无内容');
                            return false;
                        }else{
// (1)创建元素
var li = document.createElement('li');
// (2)给li添加文本
li.innerHTML = text.value;
// (3)添加元素
// ul.appendChild(li);
ul.insertBefore(li,ul.children[0]);
                        }
                    }
                </script>

        5.删除节点
            node.removeChild(child)
            // 从DOM中删除一个子节点,返回删除的节点
                <body>
                    <button>删除</button>
                    <ul>
                        <li>熊大</li>
                        <li>熊二</li>
                        <li>光头强</li>
                    </ul>
                    <script>
                        // 1.获取元素
                        var ul = document.querySelector('ul');
                        var btn = document.querySelector('button');
                        // 2.删除元素
                        // console.log(ul.removeChild(ul.children[0]));
                        // 3.点击按钮依次删除里面的孩子
                        btn.onclick = function(){
                            if(ul.children.length == 0){
                                this.disabled = true;
                            }else{
                                ul.removeChild(ul.children[0]);
                            }
                        }
                    </script>
        
        案例:删除留言
                    <style>
                        ul{
                            margin-top: 50px;
                        }
                        li{
                            width:300px;
                            padding: 5px;
                            background-color: rgb(245,209,243);
                            color: red;
                            font-size: 14px;
                            margin: 15px 0;
                        }
                        li a{
                            float: right;
                        }
                    </style>
                    <textarea name="" id="" cols="30" rows="10"></textarea>
                    <button>发布</button>
                    <ul>
                    </ul>
                    <script>
                        // 1.获取元素
                        var btn = document.querySelector('button');
                        var text = document.querySelector('textarea');
                        var ul = document.querySelector('ul');
                        // 2.绑定事件
                        btn.onclick = function () {
                            if (text.value == '') {
                                alert('无内容');
                                return false;
                            } else {
                                // (1)创建元素
                                var li = document.createElement('li');
                                // (2)给li添加文本
                                li.innerHTML = text.value + "<a href = 'javascript:;'>删除</a>";    
                                // (3)添加元素
                                // ul.appendChild(li);
                                ul.insertBefore(li, ul.children[0]);
                                // (4)删除元素 删除的当前链接的 li   父亲
                                var as = document.querySelectorAll('a');
                                for(var i = 0;i<as.length;i++){
                                    as[i].onclick = function(){
                                        // node.removeChild(child)   删除的是li   当前a所在的li   this.parentNode
                                        ul.removeChild(this.parentNode);
                                    }
                                }
                            }
                        }
                    </script>

        6.复制节点
            node.cloneNode()
            // 返回调用该方法的节点的一个副本,也成为克隆/拷贝节点
            注意: // 1.如果括号参数为空或者为false,这是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点(元素节点、文本节点等)
                  // 2.如果括号参数为true,这是深拷贝,即复制节点本身以及里面的所有子节点,且会随着复制源的改变而改变

        案例:动态生成表格
                <style>
                    table{
                        width: 500px;
                        margin: 100px auto;
                        border-collapse: collapse;
                        text-align: center;
                    }
                    td,th{
                        border: 1px solid #333;
                    }
                    thead tr{
                        height: 40px;
                        background-color: #ccc;
                    }
                </style>
                <table cellspacing="0">
                    <thead>
                        <tr>
                            <th>姓名</th>
                            <th>科目</th>
                            <th>成绩</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody> </tbody>
                </table>
                <script>
                    // 1.先准备好学生的数据
                    var datas = [
                        {
                            name: '学生一',
                            subject: 'JavaScript',
                            score: 100
                        },
                        {
                            name: '学生二',
                            subject: 'JavaScript',
                            score: 100
                        },
                        {
                            name: '学生三',
                            subject: 'JavaScript',
                            score: 100
                        }
                    ];
                    // 2.向tbody 里面创建行,有几个人(通过数组的长度)就创建几行
                    var tbody = document.querySelector('tbody');
                    // 外面的for循环管行
                    for(var i = 0;i<datas.length;i++){
                        // 1.创建 tr 行
                        var tr = document.createElement('tr');
                        tbody.appendChild(tr);
                        // 2.行里面创建单元格(跟数据有关系的三个单元格) td  单元格的数量取决于每个对象里面的属性个数  通过for循环遍历对象
                        // 里面的for循环管列 td
                        for(var k in datas[i]){
                            // 创建单元格
                            var td = document.createElement('td');
                            // 把对象里面的属性值 datas[i][k] 给 td
                            td.innerHTML = datas[i][k];
                            tr.appendChild(td);
                        }
                        // 3.创建删除单元格
                        var td = document.createElement('td');
                        td.innerHTML = '<a href="javascript:;">删除</a>';
                        tr.appendChild(td);
                    }
                    // 4.删除操作
                    var as = document.querySelectorAll('a');
                    for(var i = 0;i<as.length;i++){
                        as[i].onclick =  function(){
                            // 点击 a 删除当前a所在的行(链接的爸爸的爸爸)    node.removeChild(child)
                            tbody.removeChild(this.parentNode.parentNode);
                        }
                    }
                    // for(k in obj){
                    //     k 得到的是属性名
                    //     obj[k]得到的是属性值
                    // }
                </script>

        7.三种动态创建元素的方式及区别
            (1)document.write()
                // 如果页面文档流加载完毕 再调用这句话,会导致页面重绘
            (2)element.innerHTML
                // 是将内容写入某个DOM节点,不会导致页面全部重绘
                // 创建多个元素,如果采用拼接字符串的方式创建元素时,效率很低
                // 创建多个元素,如果采用数组形式拼接,效率很高
            (3)document.createElement
                // 创建多个元素效率不如 innerHTML 的数组形式 高于innerHTML的拼接字符串形式,但是有点在于解构清晰
            总结:innerHTML 采取数组的形式 效率要比createElement高

                    <button>点击</button>
                    <p>abc</p>
                    <div class="inner"></div>
                    <div class="create"></div>
                    <script>
                        // 三种创建元素方式区别
                        // 1.document.write()  创建元素
                        var btn = document.querySelector('button');
                        btn.onclick = function(){
                            document.write('<div>123</div>');
                        }
                        // 2.innerHTML 创建元素
                        // (1)字符串拼接的方式   效率低
                        var inner = document.querySelector('.inner');
                        for(var i = 0;i<=1000;i++){
                            inner.innerHTML += '<a href="#">百度</a>';
                        }  
                        // (2)数组形式拼接    效率高
                        var arr = [];
                        for(var i = 0;i<=100;i++){
                            arr.push('<a href="#">百度</a>');    // 向数组中添加元素   
                        }
                        inner.innerHTML = arr.join('');     // 数组转换为字符串
                        // 3.document.createElement() 创建元素
                        var create = document.querySelector('.create');
                        for(var i = 0;i<=1000;i++){
                            var a = document.createElement('a');
                            create.appendChild(a);
                        }
                    </script>
            
    5.DOM重点核心
        文档对象模型(Document Object Model)是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口
        1.对于HTML,dom使得html形成了一颗dom树,包含文档、元素、节点
        2.对于javascript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口
        // 整个页面就是一个文档,页面中所有的标签都叫做元素,页面中所有的内容都是节点(文档、元素、属性、文本)
        注意:获取过来的DOM元素是一个对象(object),所以称为文档对象模型

        1.创建元素:
            (1)document.write
            (2)innerHTML
            (3)createElement
        2.增添元素
            (1)appendChild
            (2)insertBefore
        3.删除元素
            (1)removeChild
        4.修改元素
            主要修改dom的元素的属性,dom元素的内容、属性,表单的值等
            (1)修改元素属性:src、href、title等
            (2)修改普通元素内容:innerHTML、innerText
            (3)修改表单元素:value、type、disabled等
            (4)修改元素样式:style、className
        5.查询元素
            主要获取查询dom的元素
            (1)DOM提供的API方法:getElementById、getElementsByTagName // 古老用法不太推荐
            (2)H5提供的新方法:querySelector、querySelectorAll  // 提倡用这种
            (3)利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、
            nextElementSibling)     // 提倡
        6.属性操作
            主要针对于自定义属性
            (1)setAttribute:设置dom的属性值
            (2)getAttribute:得到dom的属性值
            (3)removeAttribute:移除属性
        7.事件操作
            给元素注册事件,采取 事件源.事件类型 = 事件处理程序
            
    6.事件高级
        1.注册事件(绑定事件)
            (1)传统注册方式
                利用on开头的   如:onclick
                特点:注册事件的唯一性
                    // 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数   
            (2)方法监听注册方式(事件监听方式)
                addEventListener()  IE9之前版本不支持,可以使用attachEvent()代替 (不建议使用)
                特点:同一个元素同一个事件可以注册多个监听器
                eventTarget.addEventListener(type,listener[,useCapture]);
                //eventTarget.addEventListener()方法将指定的监听器注册到eventTarget(目标对象)上,
                //当该对象触发指定的事件时,就会执行事件处理函数
                三个参数:
                (1)type:事件类型字符串,必定加引号,而且不带on,比如click、mouseover,注意这里不要带on
                (2)listener:事件处理函数,事件发生时,会调用该监听函数
                (3)useCapture:可选参数,是一个布尔值,默认是false
                    <button>传统注册事件</button>       
                    <button> 方法监听注册事件 </button>
                    <script>
                        var btns = document.querySelectorAll('button');
                        // 1.传统方式注册事件   
                        // 具有唯一性,存在覆盖问题
                        btns[0].onclick = function(){
                            alert('hi');      
                        }
                        btns[0].onclick = function(){
                            alert('how are you');   
                        }
                        // 2.事件监听注册事件  
                        // (1)addEventListener 里面的事件类型是字符串,必定加引号,而且不带on
                        // (2)同一个元素 同一个事件可以添加多个监听器(事件处理函数)
                        btns[1].addEventListener('click',function(){
                            alert(22);
                        })
                        btns[1].addEventListener('click', function () {
                            alert(33);
                        })
                    </script>
            (3)attachEvent() 事件监听方式
                // 可以替代addEventListener()   但不建议使用
                eventTarget.attachEvent(eventNameWithOn,callback)
                //eventTarget.attachEvent()方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,指定的回调函数就会被执行
                参数:
                (1)eventNameWithOn:事件类型字符串,比如onclick、onmouseover,这里腰带on
                (2)callback:事件处理函数,当目标触发事件时回调函数被调用
            (4)注册事件兼容性解决方案
                //兼容性处理的原则,首先照顾大多数浏览器,再处理特殊浏览器
                function addEventListener(element,eventName,fn){
                    //判断当前浏览器是否支持 addEventListener() 方法
                    if(element.addEventListener){
                        element.addEventListener(eventName,fn);    //第三个参数 默认是false
                    }else if(element.attachEvent){
                        element.attachEvent('on'+eventName,fn);
                    }else{
                        // 相当于element.onclick = fn;
                        element['on'+eventName] =fn;
                    }
                }
        2.删除事件(解绑事件)
            (1)传统注册方式
                eventTarget.onclick = null;
            (2)addEventListener  删除事件
                removeEventListener
            (3)attachEvent 删除事件    // ie9 以前版本适用
                detachEvent   
                    <style>
                        div{
                            width: 100px;
                            height: 100px;
                            background-color: pink;
                        }
                    </style>
                    <div>1</div>
                    <div>2</div>
                    <div>3</div>
                    <script>
                        var divs = document.querySelectorAll('div');
                        divs[0].onclick = function(){
                            alert(11);
                            // 1.传统方式删除事件
                            divs[0].onclick = null;
                        }
                        // 2.removeEventListener  删除事件
                        divs[1].addEventListener('click',fn);    // 里面的fn 不需要加小括号进行调用
                        function fn(){
                            alert(22);
                            divs[1].removeEventListener('click',fn);
                        }
                        // 3.attachEvent 删除事件  ie9以前版本适用
                        divs[2].attachEvent('onclick',fn1);
                        function fn1(){
                            alert(33);
                            divs[2].detachEvent('onclick',fn1);
                        }
                    </script>
            (4)删除事件兼容性解决方案
                    function removeEventListener(element,eventName,fn){
                        // 判断当前浏览器是否支持 removeEventListener 方法
                        if(element.removeEventListener){
                            element.removeEventListener(eventName,fn)  // 第三个参数,默认是false
                        }else if(element.datechEvent){
                            element.detachEvent('on'+eventName,fn);
                        }else{
                            element('on'+eventName=null);
                        }
                    }
        3.DOM事件流
            事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
            事件流描述的是从页面中接收事件的顺序

            Dom事件流分为三个阶段:
                (1)捕获阶段:由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程
                    Document -> html -> body -> div
                (2)当前目标阶段:
                    div
                (3)冒泡阶段:事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
                    div -> body -> html -> Document
            注意:
                (1)JS代码只能执行捕获或者冒泡其中的一个阶段
                (2)onclick 和 attachEvent 只能得到冒泡阶段、
                    onblur、onfocus、onmouseenter、onmouseleave   这些事件没有事件冒泡
                (3)如果addEventListener 第三个参数是 true 则处于捕获阶段 (document ->html ->body ->div.father -> div.son)
                (4)如果addEventListener 第三个参数是 false 或者省略 那么就处于冒泡阶段(div.son -> div.father ->body ->html ->document)
                (5)addEventListener(type,listener[,useCapture])  第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;
                    如果是false(不写默认是false),表示在事件冒泡阶段调用事件处理程序
                (6)实际开发中,更关注事件冒泡

                    <style>
                        .father{
                            height: 200px;
                            width: 200px;
                            background-color: pink;
                        }
                        .son{
                            width: 100px;
                            height: 100px;
                            background-color: purple;
                        }
                    </style>
                    <div class="father">
                        <div class="son">son盒子</div>
                    </div>
                    <script>
                        //(1)事件捕获阶段
                        // var son = document.querySelector('.son');
                        // son.addEventListener('click',function(){
                        //     alert('son'); // document--->html --->body --->father --->son
                        // },true);
                        // var father = document.querySelector('.father');
                        // father.addEventListener('click', function () {
                        //     alert('father'); // document--->html --->body --->father --->son
                        // }, true);
                        
                        //(2)事件冒泡阶段
                        var son = document.querySelector('.son');
                        son.addEventListener('click', function () {
                            alert('son'); //div.son -> div.father -> body -> html -> document
                        });
                        var father = document.querySelector('.father');
                        father.addEventListener('click', function () {
                            alert('father'); // div.son -> div.father -> body -> html -> document
                        });
                        document.addEventListener('click',function(){
                            alert('document'); // div.son -> div.father -> body -> html -> document
                        });
                    </script>
        4.事件对象
            (1)事件对象
                (1)event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
                (2)事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法
                    比如:
                        1.谁绑定了这个事件
                        2.鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
                        3.键盘触发事件的话,会得到键盘的相关信息,如按了哪个键
                (3)eventTarget.onclick = function(event){
                        // 这个event就是事件对象,我们还喜欢写成 e 或者 evt
                    }
                    eventTarget.addEventListener('click',function(event){
                        // 这个event就是事件对象,我们还喜欢写成 e 或者 evt
                    })
                    这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去
                    当我们注册事件时,event对象就会被系统自动创建,并以此传递给事件监听器(事件处理函数)
                (4)事件对象的兼容性问题
                    事件对象本身的获取存在兼容问题:
                    1.标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到
                    2.在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找
                    3.解决:   e = e || window.event   
                    <style>
                        div{
                            width: 100px;
                            height: 100px;
                            background-color:pink;
                        }
                    </style>
                    <div>123</div>
                    <script>
                        // 事件对象
                        var div = document.querySelector('div');
                        // 1. event 就是一个事件对象 写到我们监听函数的 小括号里面  当形参来看
                        // 2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
                        // 3. 事件对象是我们事件的一系列相关数据的集合 跟事件相关的,比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件,里面就包含了键盘事件的信息,比如:判断用户按下了哪个键
                        // 4. 这个事件对象可以自己命名  如:e
                        // 5. 事件对象也有兼容性问题 ie678 通过 window.event 兼容性的写法: e = e  || window.event

                        // div.onclick = function(event){
                        //     e = e || window.event            兼容性写法
                        //     console.log(event);
                        //     console.log(window.event);      ie678 识别
                        // }

                        div.addEventListener('click',function(e){
                            console.log(e);
                        })
                    </script>
            (2)事件对象常见属性和方法
             一、this                    返回绑定事件的对象      标准
                e.currentTarget         返回绑定事件的对象      非标准 ie6~8使用

             二、e.target                返回触发事件的对象      标准
                e.srcElement            返回触发事件的对象      非标准 ie6~8使用

             三、e.type                  返回事件的类型 比如 click、mouseover  不带on

             四、e.returnValue           该属性阻止默认事件(默认行为)  非标准 ie6~8 使用 比如不让链接跳转
                e.preventDefault()      该方法阻止默认事件(默认行为)  标准  比如不让链接跳转

             五、e.stopPropagation()     该方法阻止冒泡      标准
                e.cancelBubble          该属性阻止冒泡      非标准 ie6~8使用
            
                (a)e.target 和 this 的区别:
                    <style>
                        div{
                            width: 100px;
                            height: 100px;
                            background-color:pink;
                        }
                    </style>
                    <div>123</div>
                    <script>
                        // 事件对象
                        var div = document.querySelector('div');
                        // 1. event 就是一个事件对象 写到我们监听函数的 小括号里面  当形参来看
                        // 2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
                        // 3. 事件对象是我们事件的一系列相关数据的集合 跟事件相关的,比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件,里面就包含了键盘事件的信息,比如:判断用户按下了哪个键
                        // 4. 这个事件对象可以自己命名  如:e
                        // 5. 事件对象也有兼容性问题 ie678 通过 window.event 兼容性的写法: e = e  || window.event

                        // div.onclick = function(event){
                        //     e = e || window.event            兼容性写法
                        //     console.log(event);
                        //     console.log(window.event);      ie678 识别
                        // }

                        div.addEventListener('click',function(e){
                            console.log(e);
                        })
                    </script>
                (b)e.type 和 阻止事件默认行为
                    <div>123</div>
                    <a href="http://www.baidu.com">百度</a>
                    <form action="http://www.baidu.com">
                        <input type="submit" value="提交" name="sub">
                    </form>
                    <script>
                        // 常见事件对象的属性和方法
                        // 1. 返回事件类型
                        var div = document.querySelector('div');
                        div.addEventListener('click',fn);
                        div.addEventListener('mouseover', fn);
                        div.addEventListener('mouseout', fn);
                        function fn(e){
                            console.log(e.type);    // mouseover click mouseout
                        }

                        // 2.阻止默认行为(事件)让链接跳转 或者让提交按钮不提交
                        var a = document.querySelector('a');
                        a.addEventListener('click',function(e){
                            e.preventDefault();     // dom 标准写法
                        })
                        
                        // 3. 传统注册方式
                        a.onclick = function(e){
                            // 普通浏览器   e.preventDefault();    方法
                            e.preventDefault();

                            // 低版本浏览器  ie678  returnValue    属性
                            e.returnValue;

                            // 可以利用 return false  也能阻止默认行为 且没有兼容性问题  
                            // 特点 :  ruturn 后面的代码不执行 且只限于传统的注册方式
                            return false;
                        }
                    </script>
                (3)阻止事件冒泡   
                    e.stopPropagation();     标准
                    e.cancelBubble = true;   非标准    // cancle 取消 , bubble 泡泡
                    // 阻止事件冒泡的兼容性解决方案
                        if(e && e.stopPropagation){
                            e.stopPropagation();
                        }else{
                            window.event.cancelBubble = true;
                        }
                    // 阻止事件冒泡
                    <> demo <>
                        <style>
                            .father {
                                height: 200px;
                                width: 200px;
                                background-color: pink;
                            }
                            .son {
                                width: 100px;
                                height: 100px;
                                background-color: purple;
                            }
                        </style>
                        <div class="father">
                            <div class="son">son盒子</div>
                        </div>
                        <script>
                            //(2)事件冒泡阶段
                            // 阻止事件冒泡   dom 推荐的标准 e.stopPropagation()
                            var son = document.querySelector('.son');
                            son.addEventListener('click', function (e) {
                                alert('son'); //div.son -> div.father -> body -> html -> document
                                e.stopPropagation();    // 标准    stop 停止 Propagation 传播
                                e.cancelBubble = true;    // 非标准    cancle 取消  bubble 泡泡
                            });
                            
                            var father = document.querySelector('.father');
                            father.addEventListener('click', function () {
                                alert('father'); // div.son -> div.father -> body -> html -> document
                            });
                            document.addEventListener('click', function () {
                                alert('document'); // div.son -> div.father -> body -> html -> document
                            });

                            // 阻止事件冒泡的兼容性解决方案
                            if(e && e.stopPropagation){
                                e.stopPropagation();
                            }else{
                                window.event.cancelBubble = true;
                            }
                        </script>
                (4)事件委托(代理、委托)
                    a.事件委托也成为事件代理,在jQuery里面成为事件委托
                    b.事件委托的原理:
                        不是给每一个子节点单独设置事件监听器,而是将事件监听器设置在其父节点上,然后利用冒泡原理来影响设置每个子节点
                    c.事件委托带来的好处:
                        只操作了一次DOM,提高了程序的性能
                    <> demo <>
                        <ul>
                            <li>知否知否</li>
                            <li>知否知否</li>
                            <li>知否知否</li>
                        </ul>
                        <script>
                            // 事件委托的核心原理:给父节点添加监听器,利用事件冒泡来影响每一个子节点
                            var ul = document.querySelector('ul');
                            ul.addEventListener('click',function(e){
                                // alert('知否知否');
                                // e.target  这个可以得到我们点击的对象
                                e.target.style.backgroundColor = 'pink';
                                // 再加入排他思想
                            })
                        </script>
                (5)新增的鼠标事件:
                    1. contextmenu     禁止鼠标右键菜单
                        contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
                        document.addEventListener('contextmenu',function(e){
                            e.preventDefault();    // 阻止事件的默认行为
                        })
                    2. selectstart     禁止鼠标选中
                        document.addEventListener('selectstart',function(e){
                            e.preventDefault();    // 阻止事件的默认行为
                        })
                    <> demo <>
                        <div>我是一段不愿意分享的文字</div>
                        <script>
                            // 1. contextmenu 可以用来禁用鼠标右键菜单
                            document.addEventListener('contextmenu',function(e){
                                e.preventDefault();
                            })
                            // 2. selectstart 禁止选中文字
                            document.addEventListener('selectstart',function(e){
                                e.preventDefault();
                            })
                        </script>
                (6)鼠标事件对象
                    event 对象代表事件的状态,跟事件相关的一系列信息的集合
                    1.PointerEvent  代表鼠标事件对象
                        e.clientX           返回鼠标相对于浏览器窗口可视区的X坐标
                        e.clientY           返回鼠标相对于浏览器窗口可视区的Y坐标
                        
                        e.pageX             返回鼠标相对于文档页面的X坐标 IE9+支持
                        e.pageY             返回鼠标相对于文档页面的Y坐标 IE9+支持

                        e.screenX           返回鼠标相对于电脑屏幕的X坐标
                        e.screenY           返回鼠标相对于电脑屏幕的X坐标     
                     <>DEMO<>    
                         <style>
                            body{
                                height: 3000px;
                            }
                        </style>
                        <script>
                            // 鼠标事件对象    PointerEvent
                            document.addEventListener('click',function(e){    // e 就是事件对象
                                // 1. client   鼠标在浏览器可视区的x和y坐标
                                console.log(e.clientX);        
                                console.log(e.clientY);
                                console.log(e);
                                console.log('-------------------');
                                // 2. page    鼠标在页面文档的x和y坐标
                                console.log(e.pageX);
                                console.log(e.pageY);   
                                console.log('-------------------');   
                                // 3. screen   鼠标在整个屏幕的x和y坐标
                                console.log(e.screenX);
                                console.log(e.screenY);
                            })
                        </script>
                     案例:跟随鼠标的天使(图片跟着鼠标移动)
                        鼠标移动事件:mousemove
                        页面中移动:给document注册事件
                        核心原理:鼠标每次移动,我们都会获得最新的鼠标坐标,把这个x和y坐标作为图片的top和left值就可以移动图片
                                <style>
                                    img{
                                        position: absolute;
                                    }
                                </style>
                                <img src="../../images/关闭.png" alt="">
                                <script>
                                    var pic = document.querySelector('img');
                                    document.addEventListener('mousemove',function(e){
                                        // 1. mousemove  只要鼠标移动1px  就会触发这个事件
                                        // console.log(e);
                                        // 2.核心原理:每次鼠标移动,我们都会获得最新的鼠标坐标,把这个x和y坐标作为图片的top和left值就可以移动图片
                                        var x = e.pageX;
                                        var y = e.pageY;
                                        // 3. 千万不要忘记给left 和top 添加px 单位
                                        pic.style.left = x - 100 + 'px';
                                        pic.style.top = y - 100 + 'px';
                                    })
                                </script>
                (7)键盘事件对象
                    1.KeyboardEvent 代表键盘事件对象
                        传统注册方法:  需要加on
                            onkeyup         某个键盘按键被松开时触发
                            onkeydown       某个键盘按键被按下时触发    
                            onkeypress      某个键盘按键被按下时触发    但是它不识别功能键  比如:       ctrl、 shift、箭头等
                        使用addEventListener 不需要加on
                            keyup
                            keydown
                            keypress
                        三个事件的执行顺序: keydown -> keypress -> keyup
                        <> demo <>
                            <script>
                            // 常用的键盘事件
                            // 1. keyup  按键弹起的时候触发
                            // 传统注册方法   加on
                            // document.onkeyup = function(){
                            //     console.log('我弹起了');
                            // }
                            document.addEventListener('keyup',function(){
                                console.log('我弹起了');
                            })
                            // 2. keydown 按键按下的时候触发
                            document.addEventListener('keydown', function () {
                                console.log('我按下了');
                            })
                            // 3. keypress 按键按下的时候触发     不能识别功能键  如:ctrl、shift、箭头等
                            document.addEventListener('keypress',function(){
                                console.log('我按下下了');
                            })
                            // 4. 三个事件的执行顺序   keydown --> keypress --> keyup
                        </script>
                    2.键盘事件对象:
                        键盘事件对象中的keyCode 属性可以得到相应键的ASCII码值
                        可以利用keyCode 返回的ASCII码值判断用户按下了哪个键
                            keyCode         返回该键的ASCII码值
                        ASCII码值:
                                    1:49
                                    A:65
                                    a:97
                        (1)keyup 和 keydown 这两个事件不区分字母大小写  a和A   keyCode 属性得到的都是65
                        (2)实际开发中,更多的使用keyup 和 keydown,它能识别所有的键(包括功能键)
                        (3)keypress 不识别功能键,但是keyCode属性能区分字母大小写 返回不同的ASCII码值   a:97  A:65
                案例:模拟京东按键输入内容
                        <input type="text">
                        <script>
                            // 核心思路:检测用户是否按下了s键,如果按下了s键,就把光标定位到搜索框里面
                            // 使用键盘事件对象里面的keyCode 判断用户按下的是否是s键
                            // 搜索框获得焦点:使用js 里面的focus() 方法
                            var search = document.querySelector('input');
                            document.addEventListener('keyup',function(e){       // 键盘弹起的时候触发
                                console.log(e.keyCode);
                                if(e.keyCode === 83){
                                    search.focus();
                                }
                            })
                        </script>
                案例:模拟京东快递单号查询
                    注意:(1)keydown 和 keypress 在文本框里面的特点:他们两个事件触发的时候,文字还没有落入文本框中
                         (2)keyup 事件触发的时候,文字已经落入文本框里面了
                    <style>
                        .search{
                            position: relative;
                            width: 178px;
                            margin: 100px;
                        }
                        .con{
                            display: none;
                            position: absolute;
                            top: -40px;
                            width: 171px;
                            border: 1px solid rgba(0, 0, 0, .2);
                            box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
                            padding: 5px 0;
                            font-size: 18px;
                            line-height: 20px;
                            color: #333;
                        }
                        .con::before{
                            content: '';
                            width: 0;
                            height: 0;
                            position: absolute;
                            top: 28px;
                            left: 18px;
                            border: 8px solid #000;
                            border-style: solid dashed dashed;
                            border-color: #fff transparent transparent;
                        }
                    </style>
                    <div class="search">
                        <div class="con">123</div>
                        <input type="text" placeholder="请输入您的快递单号" class="jd">
                    </div>
                    <script>
                        // 1.快递单号输入内容时:上面的大号字体盒子(con)显示(这里面的自豪更大)
                        // 2.表单检测用户输入:给表单添加键盘事件
                        // 3.同时把快递单号里面的值(value)获取过来赋值给con盒子(innerText)作为内容
                        // 4.如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子
                        var con = document.querySelector('.con');
                        var jd_input = document.querySelector('.jd');
                        jd_input.addEventListener('keyup',function(){
                            // console.log('输入内容');
                            if(this.value == ''){
                                con.style.display  = 'none';
                            }else{
                                con.style.display = 'block';
                                con.innerText = this.value;
                            }
                        })
                        // 5.当我们失去焦点,就隐藏这个con盒子
                        jd_input.addEventListener('blur',function(){
                            con.style.display = 'none';
                        })
                        // 6.当我们获得焦点,并且这个文本框内容不为空,就显示这个con盒子
                        jd_input.addEventListener('focus', function () {
                            if(this.value !== ''){
                                con.style.display = 'block';
                            }
                        })
                    </script>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值