WebAPIs

API 应用程序编程接口,是一些预定义的函数,开发者无需知道其内部的具体实现代码,只需要知道其功能是什么直接调用即可。

Web API 是浏览器提供的一套操作浏览器功能和页面元素的API (DOM和BOM),主要用于做页面交互效果。

DOM 文档对象模型

是w3c组织推荐的处理可扩展标记语言的标准编程接口,通过这些DOM接口可以改变网页内容、结构和样式。

DOM树

文档  document  一个网页就是一个文档                   

元素  element 页面中所有标签都是元素

节点  node   网页中所有内容都是节点(标签、属性、文本、注释等)

获取页面元素

getElementById()  // 通过id值获取,返回元素对象

getElementsByTagName()  // 通过标签名获取,返回元素对象的集合,以伪数组的形式存储

getElementsByClassName()  // h5新增,通过类名获取,返回元素对象集合

querySelector('选择器')  // h5新增,通过选择器获取,返回指定选择器的第一个元素对象

querySelectorAll('选择器') // h5新增,通过选择器获取,返回指定选择器的所有元素集合

获取特殊元素

document.body   // 获取body元素

document.documentElement  // 获取html元素

事件基础

事件:触发 - 响应 的一种机制,是一种可以被JS侦测到的行为。

事件三要素:事件源、事件类型、事件处理程序。

执行事件的三步骤:获取事件源、注册事件(绑定事件)、添加事件处理程序(采用函数赋值的形式)

常见的鼠标事件:onclick、onmouseover、onmouseout、onfocus、onblur、onmousemove、onmouseup、onmousedown、contextmenu 鼠标右键菜单、selectstart 开始选中

常见的键盘事件:onkeyup   onkeydown  onkeypress 不识别功能键,如ctrl shift

改变元素内容

element.innerText  // 不识别html标签,去除换行和空格

element.innerHTML  // 识别html标签,保留换行和空格

修改元素属性

element.属性名  // 普通元素属性 src href  id alt  title等  表单元素属性 type  value  checked  selected disabled等  , 只能获取到元素内置属性

element.getAttribute('属性名')  // 可以获取到自定义属性

element. setAttribute('属性名','值') // 设置自定义属性值

element.removeAttribute('属性名')  // 移除自定义属性值

自定义属性:主要用于保存与使用数据,有些数据可以保存到页面中,而不需要写入数据库里。h5规定自定义属性以data-开头。element.dataset.自定义属性名  或 element.dataset['属性名'] 也可以获取到自定义的属性值 ,如果自定义属性名使用了多个-分隔,获取时使用驼峰名称。

修改样式属性

element.style.样式名称  // 行内样式,样式名称采用驼峰命名法

element.className  // 类名样式 , 会覆盖原先的类名

 案例:全选与全不选

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>全选与全不选</title>
    <style>
        table,
        th,
        td {
            /*细边框*/
            border-collapse: collapse;
            border: 1px solid #ccc;
        }
        
        table {
            margin: 100px auto;
            width: 300px;
        }
        
        tr {
            line-height: 30px;
        }
        /*表头*/
        
        #t_th tr {
            background: #0099CD;
            color: #fff;
            font-size: 14px;
        }
        /*tbody中的行*/
        
        #t_tb tr {
            background: #EFF0EF;
            color: #7E6467;
            font-size: 12px;
        }
        /*tbody中的单元格*/
        
        #t_tb tr td {
            padding-left: 10px;
        }
        /*鼠标移入颜色*/
        
        .overColor {
            background: #F8FAF8!important;
        }
        /*鼠标移出颜色*/
        
        .outColor {
            background: #EFF0EF!important;
        }
    </style>
</head>

<body>
    <form action="#" method="post">
        <table>
            <thead id="t_th">
                <tr>
                    <th><input type="checkbox" id="cbAll" /></th>
                    <th>商品</th>
                    <th>价格</th>
                </tr>
            </thead>
            <tbody id="t_tb">
                <tr>
                    <td><input type="checkbox" /></td>
                    <td>iPhone8</td>
                    <td>800</td>
                </tr>
                <tr>
                    <td><input type="checkbox" /></td>
                    <td>iPad Pro</td>
                    <td>5000</td>
                </tr>
                <tr>
                    <td><input type="checkbox" /></td>
                    <td>iPad Air</td>
                    <td>2000</td>
                </tr>
            </tbody>
        </table>
    </form>

    <script>
        /* 鼠标移入背景变色 */
        // 获取tbody中的所有行
        var trs = document.getElementById('t_tb').getElementsByTagName('tr');
        // 为tbody中所有行添加鼠标移入和移出事件
        for (var i = 0; i < trs.length; i++) {
            // 绑定鼠标移入事件
            trs[i].onmouseover = function() {
                this.className = 'overColor';
            }

            // 绑定鼠标移出事件
            trs[i].onmouseout = function() {
                this.className = 'outColor';
            }

        }

        /* 全选与全不选 */
        // 获取全选复选框
        var cbAll = document.getElementById('cbAll');
        // 获取tbody中所有复选框
        var cbs = document.getElementById('t_tb').getElementsByTagName('input');
        // 为全选复选框添加点击事件
        cbAll.onclick = function() {
            // 如果全选复选框选中,则tbody中所有复选框也会跟着选中。
            // 如果全选复选框未选中,则tbody中所有复选框也会跟着未选中。
            // 总结:当点击全选复选框时,tbody中的所有复选框状态应该是与全选复选框状态是一致的
            for (var i = 0; i < cbs.length; i++) {
                cbs[i].checked = this.checked;
            }
        }

        // 为tbody中所有复选框添加鼠标点击事件
        for (var i = 0; i < cbs.length; i++) {
            cbs[i].onclick = function() {
                // 默认假设全选复选框为选中状态
                var flag = true;
                for (var j = 0; j < cbs.length; j++) {
                    // 如果tbody中复选框有未选中的状态,此时将全选按钮状态也设置为未选中
                    if (cbs[j].checked === false) {
                        flag = false;
                        // 为了提高代码执行效率,只要发现有一个是未选中状态即可跳出循环
                        break;
                    }
                }
                // 更新全选复选框状态
                cbAll.checked = flag;
            }
        }
    </script>
</body>

</html>

 案例:选项卡

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>选项卡</title>
    <style>
        .box {
            margin: 100px auto;
            width: 500px;
        }
        
        .box ul {
            margin: 0;
            padding: 0;
            list-style: none;
            border: 1px solid #ccc;
            background: #EFF0EF;
            overflow: hidden;
        }
        
        .box ul li {
            float: left;
            width: 80px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            font-size: 14px;
        }
        
        .tab_con div {
            display: none;
        }
        
        .current {
            color: #fff;
            background: #C71522;
        }
    </style>
</head>

<body>
    <!--列表项数量li个数与内容项item个数要一致-->
    <div class="box">
        <div class="tab_list">
            <ul>
                <li class="current">商品详情</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>
    </div>

    <script>
        // 获取列表项
        var lis = document.querySelector('.tab_list').querySelectorAll('li');
        // 获取内容项
        var items = document.querySelectorAll('.item');

        // 为每个列表项添加鼠标单击事件
        for (var i = 0; i < lis.length; i++) {
            // 为每个列表项添加索引号
            lis[i].setAttribute('index', i);
            // 列表项鼠标单击事件
            lis[i].onclick = function() {
                // 先清除所有列表项样式,再设置当前列表项背景样式
                for (var j = 0; j < lis.length; j++) {
                    lis[j].className = '';
                }
                this.className = 'current';

                // 先隐藏所有内容项,再显示对应内容项
                for (var k = 0; k < items.length; k++) {
                    items[k].style.display = 'none';
                }
                var index = this.getAttribute('index');
                items[index].style.display = 'block';
            }
        }
    </script>
</body>

</html>

节点操作

利用节点层级关系获取元素

节点属性:

  nodeType 节点类型  : 元素节点(1)  属性节点(2)  文本节点(3)  

  nodeName 节点名称  nodeValue 节点值

节点层级关系:

  父子关系: node.parentNode 父节点   parentNode.childNodes  子节点(所有的子节点,包含元素节点、文本节点等)  parentNode.children  子节点(子元素节点) parentNode.firstChild 第一个子节点(文本节点、元素节点都可以)  parentNode.lastChild  最后一个子节点 (文本节点、元素节点都可以)  parentNode.firstElementChild 第一个子元素节点 parentNode.lastElementChild 最后一个子元素节点  

      兄弟关系  node.nextSibling  下一个兄弟节点(包含元素节点、文本节点等)    node.previousSibling  上一个兄弟节点(包含元素节点、文本节点等)   node.nextElementSibling 下一个兄弟元素节点  node.previousElementSibling  上一个兄弟元素节点  

创建节点  document.createElement('标签名')    document.write() 文档流执行完毕后写入会导航页面重绘   element.innerHTML  创建多个元素时效率更高(前提不要使用拼接字符串形式,应使用数组形式接拼)

添加节点  node.appendChild(child)  后面添加节点  node.insertBefore(child,指定元素)  在指定元素前添加节点  

删除节点 node.removeChild(child)  

复制节点 node.cloneNode()  不带参数为空或false为浅克隆,只复制节点本身,不复制里面的子节点。   带参数true为深克隆,不但复制节点本身,还会复制里面的子节点

 

 案例:下拉菜单

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>下拉菜单</title>
    <style>
        /*居中显示*/
        
        .box {
            margin: 100px auto;
            width: 300px;
        }
        
        ul {
            margin: 0;
            padding: 0;
            list-style: none;
        }
        
        a {
            display: block;
            width: 100%;
            height: 100%;
            text-decoration: none;
            color: #4C4C4C;
            font-size: 12px;
        }
        /*导航项样式*/
        
        .nav_list>li {
            float: left;
            margin-right: 10px;
            width: 80px;
            height: 24px;
            line-height: 24px;
            text-align: center;
        }
        /*导航项对应下拉菜单*/
        
        .nav_list>li ul {
            display: none;
        }
        /*导航项对应下拉菜单的列表项*/
        
        .nav_list>li ul li {
            border: 1px solid #FF8500;
            border-top: none;
        }
        /*鼠标移入样式*/
        
        .overStyle {
            color: #FF8500;
            font-size: 14px;
            background: #EDEEF0;
        }
        /*鼠标移出样式*/
        
        .outStyle {
            color: #4C4C4C;
            background: #fff;
        }
    </style>
</head>

<body>
    <div class="box">
        <ul class="nav_list">
            <li>
                <a href="#">微博</a>
                <ul>
                    <li><a href="#">私信</a></li>
                    <li><a href="#">评论</a></li>
                    <li><a href="#">@我</a></li>
                </ul>
            </li>
            <li>
                <a href="#">邮箱</a>
                <ul>
                    <li><a href="#">免费邮箱</a></li>
                    <li><a href="#">VIP邮箱</a></li>
                </ul>
            </li>
        </ul>
    </div>

    <script>
        // 导航
        var navList = document.querySelector('.nav_list');
        // 导航项
        var lis = navList.children;
        // 为每个导航项添加事件
        for (var i = 0; i < lis.length; i++) {
            // 鼠标移入事件
            lis[i].onmouseover = function() {
                    // a链接添加移入样式
                    this.children[0].className = 'overStyle';
                    // 导航项对应下拉菜单显示
                    this.children[1].style.display = 'block';

                }
                // 鼠标移出事件
            lis[i].onmouseout = function() {
                // a链接添加移出样式
                this.children[0].className = 'outStyle';
                // 导航项对应下拉菜单隐藏
                this.children[1].style.display = 'none';
            }
        }
    </script>
</body>

</html>

案例: 简易留言板

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简易留言板</title>
    <style>
        .box {
            margin: 100px auto;
            width: 300px;
        }
        
        .box textarea {
            vertical-align: bottom;
            /*禁止拖拽*/
            resize: none;
            outline: none;
        }
        
        ul {
            margin-top: 20px;
            padding: 0;
            list-style: none;
            font-size: 14px;
            color: #666;
        }
        
        ul li {
            position: relative;
            height: 30px;
        }
        
        a {
            position: absolute;
            top: 3px;
            right: 3px;
            padding: 3px 6px;
            color: #fff;
            font-size: 12px;
            text-align: center;
            text-decoration: none;
            background: #f00;
            border-radius: 5px;
        }
    </style>
</head>

<body>
    <div class="box">
        <textarea cols="30" rows="3">请输入内容</textarea>
        <input type="button" value="留言" />
        <ul class="message"></ul>
    </div>

    <script>
        var ta = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        var inp = document.querySelector('input');
        // 文本域获得焦点事件
        ta.onfocus = function() {
            this.value = '';
        }

        // 留言按钮鼠标单击事件
        inp.onclick = function() {
            if (ta.value == '' || ta.value == '请输入内容') {
                alert('请输入内容');
            } else {
                // 创建li元素
                var li = document.createElement('li');
                var time = getTime();
                li.innerHTML = time + ' ' + ta.value + "<a href='javascript:;'>删除</a>";
                // 向列表最前面插入li元素
                ul.insertBefore(li, ul.children[0]);
                // 将文本域清空
                ta.value = '';

                // 删除按钮鼠标单击事件
                var a = li.querySelector('a');
                a.onclick = function() {
                    ul.removeChild(this.parentNode);
                }
            }
        }




        /*获取当前日期时间*/
        function getTime() {
            var t = new Date();
            var year = t.getFullYear();
            year = year < 10 ? '0' + year : year;
            var month = t.getMonth() + 1;
            month = month < 10 ? '0' + month : month;
            var day = t.getDate();
            day = day < 10 ? '0' + day : day;
            var hour = t.getHours();
            hour = hour < 10 ? '0' + hour : hour;
            var minute = t.getMinutes();
            minute = minute < 10 ? '0' + minute : minute;
            var second = t.getSeconds();
            second = second < 10 ? '0' + second : second;
            return '[' + year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + ']';
        }
    </script>
</body>

</html>

 阻止链接跳转   javascript:;  或 javascript:void(0);  或  事件处理函数中使用 return false; (仅适用于传统方法注册事件的情况)

 注册事件

给元素添加事件,称为注册事件或绑定事件。

传统方式:事件源.事件类型(以on开头) = 事件处理程序    // 唯一性,同一元素同一事件只能设置一个处理函数,最后注册的处理函数会覆盖前面的处理函数

方法监听:事件源.addEventListener(事件类型(不带on),事件处理程序)  // 同一个元素同一个事件可以设置多个处理函数   

ie9之前浏览器的特有: attachEvent(事件类型(带on开头),事件处理程序)  但不推荐使用

删除事件(解绑事件)

传统方式: 事件源.事件类型 = null;

方法监听:事件源.removeEventListener(事件类型,事件处理程序名称)

ie9之前浏览器的特有: detachEvent(事件类型(带on开头),事件处理程序名称)  但不推荐使用

 事件流

事件流描述从页面中接收事件的顺序。事件发生时会在元素节点之间按特定的顺序传播,这个传播过程叫做DOM事件流。

DOM事件流的3个阶段: 捕获阶段(从上往下)、当前目标阶段、冒泡阶段(从下往上)  

事件冒泡:最早由IE提出,事件开始时由最具体的元素接收,然后逐级向上播到最顶层的DOM节点的过程。

事件捕获:由网景提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素的接收过程。

JS代码只能执行捕获或冒泡其中一个阶段。onclick 和 attachEvent只能得到冒泡阶段。有些事件没有冒泡,如onblur、onfocus、onmouseenter、onmouseleave

addEventListener(事件类型(不带on),事件处理程序,true代表事件捕获阶段调用事件处理程序 false代表事件冒泡阶段调用事件处理程序)

事件对象  写在事件处理函数的小括号中,即形参位置,名称可自定义 。 ie678 需要使用window.event获取事件对象

事件发生后,一系列跟事件相关的数据集合都放在这个对象里面。 此对象是系统自动创建的。

事件对象常见属性方法: e.target  e.srcElement   e.type  e.cancelBubble  e.returnValue  e.preventDefault()  e.stropPropagation()  

鼠标事件对象常用属性方法:e.clientX  e.clientY e.pageX e.pageY  e.screenX  e.screenY  

键盘事件对象常用属性方法:e.keyCode (onkeydown onkeyup不分区大小写 onkeypress 区分大小写)

事件委托(事件代理)

不需要给每个子节点单独设置事件监听器,而是将事件监听设置在父节点上,然后利用冒泡的原理影响每个子节点。

 BOM浏览器对象模型

它提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window

window: document   location   navigation  screen  history

定义在全局作用域中的变量、函数都会变成window对象的属性和方法。

窗口加载事件

window.onload  文档内容完全加载(包括图像、链接、CSS样式文件等)后触发

document.addEventListener('DOMContentLoaded',function(){})  仅DOM加载完((不包括样式表、图片等)就会触发

窗口调整大小事件

window.onresize  只要窗口发生像素变化就会触发

window.innerWidth  当前屏幕宽度

window. innerHeight 当前屏幕宽度

定时器

var 定时器id = window.setTimeout(回调函数,延迟的毫秒数)     指定时间后执行回调函数。

window.clearTimeout(定时器id)

var 定时器id  = window.setInterval(回调函数,间隔的毫秒数)   间隔一定的时间就执行一次回调函数

window.clearInterval(定时器id)

普通函数:按代码顺序执行。

回调函数:需要等待时间,时间到了才会去调用该函数。

 JS执行队列

JS是单线程的,同一时间只能做一件事。 

html5提出了web worker标准,JS出现了同步与异步。

同步: 前一个任务执行完毕再执行后一个任务。 同步任务都在主线程上执行,形成一个执行栈。

异步:执行一个比较耗时的任务时,可以在做这个任务的同时去处理其他任务。异步任务是放在任务队列(消息队列)中执行的。异步是通过回调函数实现的。例:普通事件、资源加载、定时器。

执行机制:先执行执行栈中的同步任务,异步任务放到任务队列中,一旦执行栈中所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务放回执行栈中执行,同时清空任务队列中相应的异步任务,于是被读取的异步任务结束等待状态并开始执行。

 主线程会不断的重复获取任务,执行任务,称为事件循环。

location对象

window.location属性用来获取或设置窗口的URL,也可以用于解析URL,因为这个属性返回的是一个对象,所以也称为location对象。

URL  统一资源定位符,互联网上每一个文件都有一个唯一的URL,它包含的信息指出文件的位置及浏览器该如何处理它。

URL一般格式: 协议://主机名[:端口号]/路径/[?查询字符串]#锚点

常见属性:location.href    location.host  location.port  location.pathname  location.search  location.hash  

常见方法:location.assign() 可后退  location.replace() 不可后退  location.reload()  如果添加参数true代表强制刷新页面(相当于ctrl+F5)

navigator对象

包含有关浏览器的信息。最常用的属性 userAgent

history对象

 与浏览器历史记录进行交互。

常用方法:history.back()   history.forward()   history.go(参数)  

元素偏移量系列 offset

获取元素距离带定位的父元素的位置

获取元素自身大小(宽高,包含边框与内边距)

返回的数值不带单位

e.offsetParent  e.offsetTop  e.offsetLeft  e.offsetWidth  e.offsetHeight  

可实现的特效:模态框跟随鼠标移动、商品图放大镜效果

元素可视区系列 client

 e.clientTop  e.clientLeft  e.clientWidth  e.clientWidth

立即执行函数

(function(形参列表){// 函数体})(实参列表)   // 主要用于创建一个独立的作用域

(function(形参列表){// 函数体}(实参列表))

(function 函数名(形参列表){// 函数体}(实参列表))

三种触发load事件的情况 

a标签的超链接

F5或ctrl+F5 或 刷新按钮

前后退按钮

但firefox有个特点,有个"往返缓存"即缓存了整个页面的数据、DOM、JS状态,浏览器后退按钮不会刷新原来的页面即不会触发load事件。此时可以通过window的pageshow事件来替换实现想要的效果,此事件在页面显示时触发,它会在load事件触发后触发。此事件的事件对象有一个persisted属性可以用来判断是否为缓存中的页面触发了pageshow事件。

元素滚动系列 scroll

e.scrollTop  e.scrollLeft   e.scrollWidth  e.scrollHeight

scroll  滚动事件

页面滚动

window.pageXOffset     window.pageYOffset  页面被卷去的头部

 鼠标事件

mouseenter  只会经过自身盒子触发,经过子盒子不会触发,即它不会冒泡  。 经常搭配 mouseleave使用,mouseleave也不会冒泡

mouseover  鼠标经过自身盒子触发,经过子盒子还会触发

 

------------恢复内容开始------------

API 应用程序编程接口,是一些预定义的函数,开发者无需知道其内部的具体实现代码,只需要知道其功能是什么直接调用即可。

Web API 是浏览器提供的一套操作浏览器功能和页面元素的API (DOM和BOM),主要用于做页面交互效果。

DOM 文档对象模型

是w3c组织推荐的处理可扩展标记语言的标准编程接口,通过这些DOM接口可以改变网页内容、结构和样式。

DOM树

文档  document  一个网页就是一个文档                   

元素  element 页面中所有标签都是元素

节点  node   网页中所有内容都是节点(标签、属性、文本、注释等)

获取页面元素

getElementById()  // 通过id值获取,返回元素对象

getElementsByTagName()  // 通过标签名获取,返回元素对象的集合,以伪数组的形式存储

getElementsByClassName()  // h5新增,通过类名获取,返回元素对象集合

querySelector('选择器')  // h5新增,通过选择器获取,返回指定选择器的第一个元素对象

querySelectorAll('选择器') // h5新增,通过选择器获取,返回指定选择器的所有元素集合

获取特殊元素

document.body   // 获取body元素

document.documentElement  // 获取html元素

事件基础

事件:触发 - 响应 的一种机制,是一种可以被JS侦测到的行为。

事件三要素:事件源、事件类型、事件处理程序。

执行事件的三步骤:获取事件源、注册事件(绑定事件)、添加事件处理程序(采用函数赋值的形式)

常见的鼠标事件:onclick、onmouseover、onmouseout、onfocus、onblur、onmousemove、onmouseup、onmousedown、contextmenu 鼠标右键菜单、selectstart 开始选中

常见的键盘事件:onkeyup   onkeydown  onkeypress 不识别功能键,如ctrl shift

改变元素内容

element.innerText  // 不识别html标签,去除换行和空格

element.innerHTML  // 识别html标签,保留换行和空格

修改元素属性

element.属性名  // 普通元素属性 src href  id alt  title等  表单元素属性 type  value  checked  selected disabled等  , 只能获取到元素内置属性

element.getAttribute('属性名')  // 可以获取到自定义属性

element. setAttribute('属性名','值') // 设置自定义属性值

element.removeAttribute('属性名')  // 移除自定义属性值

自定义属性:主要用于保存与使用数据,有些数据可以保存到页面中,而不需要写入数据库里。h5规定自定义属性以data-开头。element.dataset.自定义属性名  或 element.dataset['属性名'] 也可以获取到自定义的属性值 ,如果自定义属性名使用了多个-分隔,获取时使用驼峰名称。

修改样式属性

element.style.样式名称  // 行内样式,样式名称采用驼峰命名法

element.className  // 类名样式 , 会覆盖原先的类名

 案例:全选与全不选

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>全选与全不选</title>
    <style>
        table,
        th,
        td {
            /*细边框*/
            border-collapse: collapse;
            border: 1px solid #ccc;
        }
        
        table {
            margin: 100px auto;
            width: 300px;
        }
        
        tr {
            line-height: 30px;
        }
        /*表头*/
        
        #t_th tr {
            background: #0099CD;
            color: #fff;
            font-size: 14px;
        }
        /*tbody中的行*/
        
        #t_tb tr {
            background: #EFF0EF;
            color: #7E6467;
            font-size: 12px;
        }
        /*tbody中的单元格*/
        
        #t_tb tr td {
            padding-left: 10px;
        }
        /*鼠标移入颜色*/
        
        .overColor {
            background: #F8FAF8!important;
        }
        /*鼠标移出颜色*/
        
        .outColor {
            background: #EFF0EF!important;
        }
    </style>
</head>

<body>
    <form action="#" method="post">
        <table>
            <thead id="t_th">
                <tr>
                    <th><input type="checkbox" id="cbAll" /></th>
                    <th>商品</th>
                    <th>价格</th>
                </tr>
            </thead>
            <tbody id="t_tb">
                <tr>
                    <td><input type="checkbox" /></td>
                    <td>iPhone8</td>
                    <td>800</td>
                </tr>
                <tr>
                    <td><input type="checkbox" /></td>
                    <td>iPad Pro</td>
                    <td>5000</td>
                </tr>
                <tr>
                    <td><input type="checkbox" /></td>
                    <td>iPad Air</td>
                    <td>2000</td>
                </tr>
            </tbody>
        </table>
    </form>

    <script>
        /* 鼠标移入背景变色 */
        // 获取tbody中的所有行
        var trs = document.getElementById('t_tb').getElementsByTagName('tr');
        // 为tbody中所有行添加鼠标移入和移出事件
        for (var i = 0; i < trs.length; i++) {
            // 绑定鼠标移入事件
            trs[i].onmouseover = function() {
                this.className = 'overColor';
            }

            // 绑定鼠标移出事件
            trs[i].onmouseout = function() {
                this.className = 'outColor';
            }

        }

        /* 全选与全不选 */
        // 获取全选复选框
        var cbAll = document.getElementById('cbAll');
        // 获取tbody中所有复选框
        var cbs = document.getElementById('t_tb').getElementsByTagName('input');
        // 为全选复选框添加点击事件
        cbAll.onclick = function() {
            // 如果全选复选框选中,则tbody中所有复选框也会跟着选中。
            // 如果全选复选框未选中,则tbody中所有复选框也会跟着未选中。
            // 总结:当点击全选复选框时,tbody中的所有复选框状态应该是与全选复选框状态是一致的
            for (var i = 0; i < cbs.length; i++) {
                cbs[i].checked = this.checked;
            }
        }

        // 为tbody中所有复选框添加鼠标点击事件
        for (var i = 0; i < cbs.length; i++) {
            cbs[i].onclick = function() {
                // 默认假设全选复选框为选中状态
                var flag = true;
                for (var j = 0; j < cbs.length; j++) {
                    // 如果tbody中复选框有未选中的状态,此时将全选按钮状态也设置为未选中
                    if (cbs[j].checked === false) {
                        flag = false;
                        // 为了提高代码执行效率,只要发现有一个是未选中状态即可跳出循环
                        break;
                    }
                }
                // 更新全选复选框状态
                cbAll.checked = flag;
            }
        }
    </script>
</body>

</html>

 案例:选项卡

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>选项卡</title>
    <style>
        .box {
            margin: 100px auto;
            width: 500px;
        }
        
        .box ul {
            margin: 0;
            padding: 0;
            list-style: none;
            border: 1px solid #ccc;
            background: #EFF0EF;
            overflow: hidden;
        }
        
        .box ul li {
            float: left;
            width: 80px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            font-size: 14px;
        }
        
        .tab_con div {
            display: none;
        }
        
        .current {
            color: #fff;
            background: #C71522;
        }
    </style>
</head>

<body>
    <!--列表项数量li个数与内容项item个数要一致-->
    <div class="box">
        <div class="tab_list">
            <ul>
                <li class="current">商品详情</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>
    </div>

    <script>
        // 获取列表项
        var lis = document.querySelector('.tab_list').querySelectorAll('li');
        // 获取内容项
        var items = document.querySelectorAll('.item');

        // 为每个列表项添加鼠标单击事件
        for (var i = 0; i < lis.length; i++) {
            // 为每个列表项添加索引号
            lis[i].setAttribute('index', i);
            // 列表项鼠标单击事件
            lis[i].onclick = function() {
                // 先清除所有列表项样式,再设置当前列表项背景样式
                for (var j = 0; j < lis.length; j++) {
                    lis[j].className = '';
                }
                this.className = 'current';

                // 先隐藏所有内容项,再显示对应内容项
                for (var k = 0; k < items.length; k++) {
                    items[k].style.display = 'none';
                }
                var index = this.getAttribute('index');
                items[index].style.display = 'block';
            }
        }
    </script>
</body>

</html>

节点操作

利用节点层级关系获取元素

节点属性:

  nodeType 节点类型  : 元素节点(1)  属性节点(2)  文本节点(3)  

  nodeName 节点名称  nodeValue 节点值

节点层级关系:

  父子关系: node.parentNode 父节点   parentNode.childNodes  子节点(所有的子节点,包含元素节点、文本节点等)  parentNode.children  子节点(子元素节点) parentNode.firstChild 第一个子节点(文本节点、元素节点都可以)  parentNode.lastChild  最后一个子节点 (文本节点、元素节点都可以)  parentNode.firstElementChild 第一个子元素节点 parentNode.lastElementChild 最后一个子元素节点  

      兄弟关系  node.nextSibling  下一个兄弟节点(包含元素节点、文本节点等)    node.previousSibling  上一个兄弟节点(包含元素节点、文本节点等)   node.nextElementSibling 下一个兄弟元素节点  node.previousElementSibling  上一个兄弟元素节点  

创建节点  document.createElement('标签名')    document.write() 文档流执行完毕后写入会导航页面重绘   element.innerHTML  创建多个元素时效率更高(前提不要使用拼接字符串形式,应使用数组形式接拼)

添加节点  node.appendChild(child)  后面添加节点  node.insertBefore(child,指定元素)  在指定元素前添加节点  

删除节点 node.removeChild(child)  

复制节点 node.cloneNode()  不带参数为空或false为浅克隆,只复制节点本身,不复制里面的子节点。   带参数true为深克隆,不但复制节点本身,还会复制里面的子节点

 

 案例:下拉菜单

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>下拉菜单</title>
    <style>
        /*居中显示*/
        
        .box {
            margin: 100px auto;
            width: 300px;
        }
        
        ul {
            margin: 0;
            padding: 0;
            list-style: none;
        }
        
        a {
            display: block;
            width: 100%;
            height: 100%;
            text-decoration: none;
            color: #4C4C4C;
            font-size: 12px;
        }
        /*导航项样式*/
        
        .nav_list>li {
            float: left;
            margin-right: 10px;
            width: 80px;
            height: 24px;
            line-height: 24px;
            text-align: center;
        }
        /*导航项对应下拉菜单*/
        
        .nav_list>li ul {
            display: none;
        }
        /*导航项对应下拉菜单的列表项*/
        
        .nav_list>li ul li {
            border: 1px solid #FF8500;
            border-top: none;
        }
        /*鼠标移入样式*/
        
        .overStyle {
            color: #FF8500;
            font-size: 14px;
            background: #EDEEF0;
        }
        /*鼠标移出样式*/
        
        .outStyle {
            color: #4C4C4C;
            background: #fff;
        }
    </style>
</head>

<body>
    <div class="box">
        <ul class="nav_list">
            <li>
                <a href="#">微博</a>
                <ul>
                    <li><a href="#">私信</a></li>
                    <li><a href="#">评论</a></li>
                    <li><a href="#">@我</a></li>
                </ul>
            </li>
            <li>
                <a href="#">邮箱</a>
                <ul>
                    <li><a href="#">免费邮箱</a></li>
                    <li><a href="#">VIP邮箱</a></li>
                </ul>
            </li>
        </ul>
    </div>

    <script>
        // 导航
        var navList = document.querySelector('.nav_list');
        // 导航项
        var lis = navList.children;
        // 为每个导航项添加事件
        for (var i = 0; i < lis.length; i++) {
            // 鼠标移入事件
            lis[i].onmouseover = function() {
                    // a链接添加移入样式
                    this.children[0].className = 'overStyle';
                    // 导航项对应下拉菜单显示
                    this.children[1].style.display = 'block';

                }
                // 鼠标移出事件
            lis[i].onmouseout = function() {
                // a链接添加移出样式
                this.children[0].className = 'outStyle';
                // 导航项对应下拉菜单隐藏
                this.children[1].style.display = 'none';
            }
        }
    </script>
</body>

</html>

案例: 简易留言板

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简易留言板</title>
    <style>
        .box {
            margin: 100px auto;
            width: 300px;
        }
        
        .box textarea {
            vertical-align: bottom;
            /*禁止拖拽*/
            resize: none;
            outline: none;
        }
        
        ul {
            margin-top: 20px;
            padding: 0;
            list-style: none;
            font-size: 14px;
            color: #666;
        }
        
        ul li {
            position: relative;
            height: 30px;
        }
        
        a {
            position: absolute;
            top: 3px;
            right: 3px;
            padding: 3px 6px;
            color: #fff;
            font-size: 12px;
            text-align: center;
            text-decoration: none;
            background: #f00;
            border-radius: 5px;
        }
    </style>
</head>

<body>
    <div class="box">
        <textarea cols="30" rows="3">请输入内容</textarea>
        <input type="button" value="留言" />
        <ul class="message"></ul>
    </div>

    <script>
        var ta = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        var inp = document.querySelector('input');
        // 文本域获得焦点事件
        ta.onfocus = function() {
            this.value = '';
        }

        // 留言按钮鼠标单击事件
        inp.onclick = function() {
            if (ta.value == '' || ta.value == '请输入内容') {
                alert('请输入内容');
            } else {
                // 创建li元素
                var li = document.createElement('li');
                var time = getTime();
                li.innerHTML = time + ' ' + ta.value + "<a href='javascript:;'>删除</a>";
                // 向列表最前面插入li元素
                ul.insertBefore(li, ul.children[0]);
                // 将文本域清空
                ta.value = '';

                // 删除按钮鼠标单击事件
                var a = li.querySelector('a');
                a.onclick = function() {
                    ul.removeChild(this.parentNode);
                }
            }
        }




        /*获取当前日期时间*/
        function getTime() {
            var t = new Date();
            var year = t.getFullYear();
            year = year < 10 ? '0' + year : year;
            var month = t.getMonth() + 1;
            month = month < 10 ? '0' + month : month;
            var day = t.getDate();
            day = day < 10 ? '0' + day : day;
            var hour = t.getHours();
            hour = hour < 10 ? '0' + hour : hour;
            var minute = t.getMinutes();
            minute = minute < 10 ? '0' + minute : minute;
            var second = t.getSeconds();
            second = second < 10 ? '0' + second : second;
            return '[' + year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + ']';
        }
    </script>
</body>

</html>

 阻止链接跳转   javascript:;  或 javascript:void(0);  或  事件处理函数中使用 return false; (仅适用于传统方法注册事件的情况)

 注册事件

给元素添加事件,称为注册事件或绑定事件。

传统方式:事件源.事件类型(以on开头) = 事件处理程序    // 唯一性,同一元素同一事件只能设置一个处理函数,最后注册的处理函数会覆盖前面的处理函数

方法监听:事件源.addEventListener(事件类型(不带on),事件处理程序)  // 同一个元素同一个事件可以设置多个处理函数   

ie9之前浏览器的特有: attachEvent(事件类型(带on开头),事件处理程序)  但不推荐使用

删除事件(解绑事件)

传统方式: 事件源.事件类型 = null;

方法监听:事件源.removeEventListener(事件类型,事件处理程序名称)

ie9之前浏览器的特有: detachEvent(事件类型(带on开头),事件处理程序名称)  但不推荐使用

 事件流

事件流描述从页面中接收事件的顺序。事件发生时会在元素节点之间按特定的顺序传播,这个传播过程叫做DOM事件流。

DOM事件流的3个阶段: 捕获阶段(从上往下)、当前目标阶段、冒泡阶段(从下往上)  

事件冒泡:最早由IE提出,事件开始时由最具体的元素接收,然后逐级向上播到最顶层的DOM节点的过程。

事件捕获:由网景提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素的接收过程。

JS代码只能执行捕获或冒泡其中一个阶段。onclick 和 attachEvent只能得到冒泡阶段。有些事件没有冒泡,如onblur、onfocus、onmouseenter、onmouseleave

addEventListener(事件类型(不带on),事件处理程序,true代表事件捕获阶段调用事件处理程序 false代表事件冒泡阶段调用事件处理程序)

事件对象  写在事件处理函数的小括号中,即形参位置,名称可自定义 。 ie678 需要使用window.event获取事件对象

事件发生后,一系列跟事件相关的数据集合都放在这个对象里面。 此对象是系统自动创建的。

事件对象常见属性方法: e.target  e.srcElement   e.type  e.cancelBubble  e.returnValue  e.preventDefault()  e.stropPropagation()  

鼠标事件对象常用属性方法:e.clientX  e.clientY e.pageX e.pageY  e.screenX  e.screenY  

键盘事件对象常用属性方法:e.keyCode (onkeydown onkeyup不分区大小写 onkeypress 区分大小写)

事件委托(事件代理)

不需要给每个子节点单独设置事件监听器,而是将事件监听设置在父节点上,然后利用冒泡的原理影响每个子节点。

 BOM浏览器对象模型

它提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window

window: document   location   navigation  screen  history

定义在全局作用域中的变量、函数都会变成window对象的属性和方法。

窗口加载事件

window.onload  文档内容完全加载(包括图像、链接、CSS样式文件等)后触发

document.addEventListener('DOMContentLoaded',function(){})  仅DOM加载完((不包括样式表、图片等)就会触发

窗口调整大小事件

window.onresize  只要窗口发生像素变化就会触发

window.innerWidth  当前屏幕宽度

window. innerHeight 当前屏幕宽度

定时器

var 定时器id = window.setTimeout(回调函数,延迟的毫秒数)     指定时间后执行回调函数。

window.clearTimeout(定时器id)

var 定时器id  = window.setInterval(回调函数,间隔的毫秒数)   间隔一定的时间就执行一次回调函数

window.clearInterval(定时器id)

普通函数:按代码顺序执行。

回调函数:需要等待时间,时间到了才会去调用该函数。

 JS执行队列

JS是单线程的,同一时间只能做一件事。 

html5提出了web worker标准,JS出现了同步与异步。

同步: 前一个任务执行完毕再执行后一个任务。 同步任务都在主线程上执行,形成一个执行栈。

异步:执行一个比较耗时的任务时,可以在做这个任务的同时去处理其他任务。异步任务是放在任务队列(消息队列)中执行的。异步是通过回调函数实现的。例:普通事件、资源加载、定时器。

执行机制:先执行执行栈中的同步任务,异步任务放到任务队列中,一旦执行栈中所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务放回执行栈中执行,同时清空任务队列中相应的异步任务,于是被读取的异步任务结束等待状态并开始执行。

 主线程会不断的重复获取任务,执行任务,称为事件循环。

location对象

window.location属性用来获取或设置窗口的URL,也可以用于解析URL,因为这个属性返回的是一个对象,所以也称为location对象。

URL  统一资源定位符,互联网上每一个文件都有一个唯一的URL,它包含的信息指出文件的位置及浏览器该如何处理它。

URL一般格式: 协议://主机名[:端口号]/路径/[?查询字符串]#锚点

常见属性:location.href    location.host  location.port  location.pathname  location.search  location.hash  

常见方法:location.assign() 可后退  location.replace() 不可后退  location.reload()  如果添加参数true代表强制刷新页面(相当于ctrl+F5)

navigator对象

包含有关浏览器的信息。最常用的属性 userAgent

history对象

 与浏览器历史记录进行交互。

常用方法:history.back()   history.forward()   history.go(参数)  

元素偏移量系列 offset

获取元素距离带定位的父元素的位置

获取元素自身大小(宽高,包含边框与内边距)

返回的数值不带单位

e.offsetParent  e.offsetTop  e.offsetLeft  e.offsetWidth  e.offsetHeight  

可实现的特效:模态框跟随鼠标移动、商品图放大镜效果

元素可视区系列 client

 e.clientTop  e.clientLeft  e.clientWidth  e.clientWidth

立即执行函数

(function(形参列表){// 函数体})(实参列表)   // 主要用于创建一个独立的作用域

(function(形参列表){// 函数体}(实参列表))

(function 函数名(形参列表){// 函数体}(实参列表))

三种触发load事件的情况 

a标签的超链接

F5或ctrl+F5 或 刷新按钮

前后退按钮

但firefox有个特点,有个"往返缓存"即缓存了整个页面的数据、DOM、JS状态,浏览器后退按钮不会刷新原来的页面即不会触发load事件。此时可以通过window的pageshow事件来替换实现想要的效果,此事件在页面显示时触发,它会在load事件触发后触发。此事件的事件对象有一个persisted属性可以用来判断是否为缓存中的页面触发了pageshow事件。

元素滚动系列 scroll

e.scrollTop  e.scrollLeft   e.scrollWidth  e.scrollHeight

scroll  滚动事件

页面滚动

window.pageXOffset     window.pageYOffset  页面被卷去的头部

 鼠标事件

mouseenter  只会经过自身盒子触发,经过子盒子不会触发,即它不会冒泡  。 经常搭配 mouseleave使用,mouseleave也不会冒泡

mouseover  鼠标经过自身盒子触发,经过子盒子还会触发

过渡完成事件  transitionend

 移动端事件

触屏事件   touchstart   touchmove  touchend

触屏事件对象TouchEvent属性    touches   targetTouches   changedTouches 

 classList  html5新增属性,返回元素类名

posted on 2020-07-12 08:13  TabPHP  阅读(146)  评论(0)    收藏  举报