BOM和DOM

此笔记是我在拉勾学习课程过程中的总结,文字原创,笔记里很多技巧和知识是老师总结的,如果有侵权,请联系本人!

一些基本概念

1.API:

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

2.浏览器提供的一套浏览器功能和页面元素的api(BOM和DOM)

3.一些学习资料:

MDN:https://developer.mozilla.org/zh-CN/docs/Web/API

一、DOM

1.Document Object Model,可以把一个HTML网页看做文档树,通过DOM提供的API对节点进行操作。

2.DOM树

DOM树包含的节点类型:
(标签、属性、文本、注释等)

  • 元素:网页中的标签
  • 属性:标签的属性

3.获取页面元素:

  • 根据id获取元素(id具有唯一性)
    方法:调用document对象的getElementById方法
    参数:字符串类型的id的属性值
    返回值:对应id的元素对象
// 获取页面中id值为box的元素
var box = document.getElementById('box');
  • 根据标签名获取元素
    getElementsByTagName

返回值,同名元素对象组成的伪数组 htmlcollection
操作时按数组方法操作,且元素动态增加

// 提前获取元素
var divs = document.getElementsByTagName("div");

  • 元素对象内部获取元素

获取元素对象内部,本身也可以调用根据标签获取元素方法,类似于css后代选择器

//   元素对象内部可以继续打点调用通过标签名获取元素的方法
// 类似于css中 后代选择器,缩小选择范围
var  box1 = document.getElementById("box1");
var ps1 = box1.getElementsByTagName("p");

  • 根据name属性获取元素(只做了解,不建议使用)

选中的元素也是动态变化的

// 获取元素中name属性值为age的元素
// 节点列表集合 NodeList
var ages = document.getElementsByName('age');
 // 兼容问题:在ie和Opera中使用,会多选中id属性值相同的元素
 // 方法选中元素是动态变化的

  • 根据类名(class)获取元素
    getElementsByClassName
    返回class属性值相同元素对象组成的伪数组 htmlcollection
    也可以动态添加
    不兼容IE8及以下浏览器
// 获取页面中所有类名为.box的元素
var box = document.getElementsByClassName('box');
  • 根据选择器获取元素
    1:通过document的querySelector方法,通过css中选择器去选择第一个符合条件的标签
    2:调用querySelectorAll ,通过css中的选择器选取所有符合条件的标签元素,返回值是 nodelist
    参数:字符串---css中的选择题
 // 在结构之后使用 选择器 选取方法,选中第一个
 var para = document.querySelector("#box1 .para"); 
 // 选择所有符合条件的元素
 var paras = document.querySelectorAll("#box1 .para");
 // 得到一个 nodelist        
// 兼容问题:ie8 以下不兼容

4.DOM事件与绑定

-执行机制:触发—响应机制

  • 绑定事件三要素:

    • 事件源:绑定给谁
    • 事件类型:绑定干什么类型事件 click,hover
    • 事件函数:事件发生后执行什么内容,写在函数内部
  • 常用的鼠标事件类型:

    事件 说明
    Onclick 鼠标左键单击
    Ondblclick 鼠标左键双击
    Onmousedown 鼠标按下触发
    Onmouseup 鼠标按键放开触发
    Onmousemove 鼠标在元素上移动
    Onmouseover 鼠标在元素上触发
    Onmouseout 鼠标移出元素边界
  • 常用的事件监听方法

    • html绑定
    <input type="button" id="btn" value="点击" onclick="alert('点我做什么?')">
    
  • 绑定dom对象

    <!-- <input type="button" id="btn" value="点击" onclick="alert('点我做什么?')"> -->
      <input type="button" id="btn" value="点击">
      <script>
          var btn = document.getElementById("btn");
          btn.onclick = function () {
              alert("我做什么?");
          }
    

5.绑定事件的其他方法

此处为了和DOM0级事件的绑定方法综合学习

5.1 DOM 0级事件绑定

  • on方法,即上述方法,采用onclick onmouseover等,只能每次绑定一个事件,如多次绑定,则先绑定的会被后面的层叠

5.2 DOM 2级事件绑定

  • Element.addEventListener()方法
    参数:
    • 第一个:事件类型字符串(需要on)
    • 第二个:事件函数
      同一个元素可以多次绑定监听,同一类型可以注册多个事件函数
      不兼容ie9以下
<input type="button" value="点击" id="btn">
    <script>
        var btn = document.getElementById("btn");
         // DOM0 级事件
        // 绑定事件的方式
        // btn.onclick = function () {
        //   alert(1);
        // };
        // 绑定多次相同的事件
        // btn.onclick = function () {
        //   alert(2);
        // };

        // DOM 2 级事件绑定方式
        btn.addEventListener("click",function () {
            alert(1);
        });
        // 多次绑定个相同的事件类型,事件会根据书写的顺序进行一个事件排队
        btn.addEventListener("click",function () {
            alert(2);
        });
        // 此处clickevent是作为参数传进来,不可以加括号,否则就直接调用了
        btn.addEventListener("click",clickEvent);
        function clickEvent () {
            alert(3);
        }
    </script>

  • element.attachEvent() 方法
    参数:
    • 第一个:事件类型字符串(需要on)
    • 第二个:事件函数
      同一元素可以多次绑定监听,同一个事件类型可以注册多个事件函数
      只兼容IE10及以下
 <input type="button" value="点击" id="btn">
    <script>
        var btn = document.getElementById("btn");    
        // DOM 2 级事件绑定方式
        // 兼容: IE 10以下
        //  IE 8 以下会出现事件队列顺序错乱
        btn.attachEvent("onclick",function() {
            alert(3);
        });
        btn.attachEvent("onclick",clickEvent);
        function clickEvent () {
            alert(4);
        }
    </script>

  • 兼容写法
    为了应对ie的兼容能力,利用浏览器的能力监测和if语句条件判断,将两种写法综合到一起
  • 参数:事件源,事件类型(不加 on),事件函数
// 自己制作一个兼容所有浏览器的绑定事件函数
    // 参数:事件源,事件类型,事件函数
    function addEvent (ele,type,fn) {
        // IE 9 及以上的浏览器和其他浏览器,使用addEventListener方法
        // IE 9 以下的浏览器,使用 attachEvent 方法
        // 浏览器能力检测
        if (ele.addEventListener) {
            ele.addEventListener(type,fn);
        }else if (ele.attachEvent) {
            ele.attachEvent("on" + type,fn);
        }
    }

5.3 事件解绑

  • DOM 0级事件解绑

ele.onclick = null

  • DOM 2级事件解绑
    element.removeEventListener() 方法

  • 参数:

    • 参数1:事件类型的字符串,直接写click
    • 参数2:事件函数应用名
      注意:没有办法移除一个匿名函数
      兼容性问题:不支持 IE9 以下的浏览器
  • element.detachEvent() 方法。

  • 参数:

    • 参数1:事件类型的字符串(需要加 on)
    • 参数2:事件函数
      注意::没有办法移除一个匿名函数
      兼容性问题:只支持 IE10 及以下的浏览器
 // DOM 0 级事件绑定方式
        // btn.onclick = function () {
        //     alert(1);
        // }
        // // 解除绑定
        // btn.onclick = null;
        // 绑定事件
        // btn.addEventListener("click",fun);
        // btn.addEventListener("click",fun2);
        // 解除绑定
        // btn.removeEventListener("click",fun);        
        // function fun() {
        //     alert(2);
        // }
        // function fun2 () {
        //     alert(3);
        // }
            // 绑定事件
            btn.attachEvent("onclick",fun1);
            // 解除绑定
            btn.detachEvent("onclick",fun);
                    function fun() {
                        alert(2);
                    }
  • 解绑事件综合写法

    • 参数:事件源,事件类型(不加 on),事件函数
 <input type="button" value="点击" id="btn">
    <script>
        var btn = document.getElementById("btn");
        addEvent(btn,"click",fun1);
        function fun1() {
            alert(1);
        }
        // DOM 2 级事件绑定方式
        // 自己制作一个兼容所有浏览器的绑定事件函数
        // 参数:事件源,事件类型,事件函数
        function addEvent (ele,type,fn) {
            // IE 9 及以上的浏览器和其他浏览器,使用addEventListener方法
            // IE 9 以下的浏览器,使用 attachEvent 方法
            // 浏览器能力检测
            if (ele.addEventListener) {
                ele.addEventListener(type,fn);
            }else if (ele.attachEvent) {
                ele.attachEvent("on" + type,fn);
            }
        }
        // 兼容所有浏览器的 解除绑定事件的函数
        // 参数:事件源,事件类型,事件函数
        function removeEvent(ele,type,fn) {
          // 浏览器能力检测
          if (ele.removeEventListener) {
            ele.removeEventListener(type,fn);
          } else if (ele.detachEvent) {
            ele.detachEvent("on" + type,fn);
          }
        }
        
    </script>

6.DOM元素属性操作

6.1非表单元素属性

如href、title、id、src等
调用:元素对象打点调用属性名,obj.href
注意:部分属性名跟关键字和保留字冲突,会更换写法
class → className
for → htmlFor
rowspan → rowSpan
属性赋值:给元素属性赋值,等号右侧的赋值都是字符串赋值

  var link = document.getElementById("link");
        var pic = document.getElementById("pic");
        // 调用元素对象的属性,从而操作 HTML 中的标签属性
        console.log(link.textContent);//获取的是文本内容
        console.log(link.href);
        console.log(link.title);
        console.log(link.id);// id 是只读属性,不可更改
        console.log(pic.id);// id 是只读属性,不可更改
        console.log(pic.src);
        console.log(pic.alt);
        console.log(pic.className);
        // 等号赋值,值必须是字符串类型
        pic.src = "images/b.jpg";

案例1:切换按钮

<input type="button" value="点击" id = "btn"><br>
    <img src="images/a.jpg" alt="美女" id = "pic">
    <script>
        // 获取元素
        var btn = document.getElementById("btn");
        var pic = document.getElementById("pic");
        // 给按钮添加点击事件
        var num = 1;
        btn.onclick = function () {
            // 给图片切换 src 属性
            // 通过 if 语句判断,如果是 a 图片,则切换为b,反之切换为 a
            if ( num === 1) {
                pic.src = "images/b.jpg";
                // 数字要跟着发生变化
                num = 2;
            }else {
                pic.src = "images/a.jpg";
                num = 1;
            }
        };

案例2:隐藏元素

<style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        .hide {
            display: none;
        }
        .show {
            display: block;
        }
    </style>
</head>
<body>
    <input type="button" value="点击隐藏" id="btn">
    <div id="box"></div>
    <script>
        // 获取元素
        var btn = document.getElementById("btn");
        var box = document.getElementById("box");
        // 点击按钮,让 div 显示或隐藏
        // box.style.display = "none";
        btn.onclick = function () {
            // 点击按钮,让 div 显示或隐藏
            // 根据 按钮 的 value 值进行条件判断
            if (btn.value === "点击隐藏") {
                box.className = "hide";
                btn.value = "点击显示";
            }else {
                box.className = "show";
                btn.value = "点击隐藏";
            }
        };
    </script>

6.2 this指向

  • 在事件函数内部 有一个 this,指向事件源
    区分一下不同函数内部 this 的指向
    • 普通函数 --> window对象
    • 构造函数 --> 指向的是生成的实例对象
    • 对象的方法 --> 指向的是对象本身
    • 事件函数 --> 指向的是事件源
 // 点击按钮,让 div 显示或隐藏
            // 根据 按钮 的 value 值进行条件判断
            if (this.value === "点击隐藏") {
                box.className = "hide";
                this.value = "点击显示";
            }else {
                box.className = "show";
                this.value = "点击隐藏";
            }
        };

        // 在事件函数内部 有一个 this,指向事件源
        // 区分一下不同函数内部 this 的指向
        // 普通函数  --> window对象
        // 构造函数  --> 指向的是生成的实例对象
        // 对象的方法 --> 指向的是对象本身
        // 事件函数  --> 指向的是事件源

6.3 获取标签内部内容的属性

获取标签内部内容的属性有两个:innerHTML和 innerText

  • innerHTML属性会获取全部内容,包括标签,获取内容的空白换行等
  • innerText属性,如果有标签,会过滤标签,获取内容也会去掉换行和空白等。
box.innerHTML; // 
box.innerText;// 
box.innerHTML = "<h2>我会识别标签</h2>";
box.innerText = "<h2>我不会识别标签</h2>";

6.4 更改标签内部内容

  • innerHTML设置属性值、有标签的字符串,会按照html语法的标签加载。
  • innerText设置有标签的属性值的时候按照普通字符加载。
    应用场景:
  • innerText设置纯字符串
  • innerHTML设施有标签的结构
// 更改标签内容、
        box.innerHTML = "<h2>hello js<\h2>";
        box.innerText = "<h2>hello js<\h2>";

6.5 表单元素操作

  • Value用于大部分表单元素内容获取(option除外)
  • type 可以获取input标签的类型(输入框或复选框等)
    • disabled 禁用属性
    • checked 复选框选中属性
    • selected 下拉菜单选中属性
    • 注意:在 DOM 中元素对象的属性值只有一个时,会被转成布尔值显示。
   <input type="text" class="gray" value="请输入搜索关键字" id="txtSearch">
  <input type="button" value="搜索" id="btnSearch">
  <script>
    //   获取元素
    var txtSearch = document.getElementById("txtSearch");
    //   1、获得焦点时,可以使用 onfocus,如果文本框内容是默认 请输入搜索关键字,,需要清空文字,让文字颜色加载黑色
    txtSearch.onfocus = function () {
        if (this.value === "请输入搜索关键字" ) {
            this.value = "";
            this.className = "black";
        }
    };
    // 2、失去焦点时,可以使用一个 onblur,如果文本框内容为空,需要改为默认提示内容, 请输入搜索关键字,让文字颜色变为灰色
    txtSearch.onblur = function () {
        // 如果用户输入内容正好与默认提示文本相同,失去焦点时,也应该让蚊子颜色变为灰色
        // 判断内容是否为空
        if (this.value === "") {
            this.value = "请输入搜索关键字";
            this.className = "gray";
        }
    };

6.6 自定义属性

• getAttribute(name) 获取标签行内属性
• setAttribute(name,value) 设置标签行内属性
• removeAttribute(name) 移除标签行内属性
• 与element.属性的区别: 上述三个方法用于获取任意的行内属性,包括自定义的属性。

 <div id="box" age="18" sex="male">小明</div>
    <script>
        // 获取元素
        var box = document.getElementById("box");
        // 元素自有属性
        console.log(box.id);
        // 元素自定义的新属性不能用点语法调用
        // 可以调用元素对象的获取自定义属性的方法
        console.log(box.getAttribute("age"));
        console.log(box.getAttribute("sex"));
        // 也可以调用自有属性
        console.log(box.getAttribute("id"));
        // 设置属性,添加新的自定义属性或者自有属性
        box.setAttribute("age","20");
        box.setAttribute("city","beijing");
        // 传的参数不需要进行属性名的修改,也可以传入原本封装好的参数,比如class
        box.setAttribute("class","demo");

        // 移除属性
        box.removeAttribute("age");
    </script>

6.7 Style属性操作

  • style的获取的值是行内样式组成的样式对象,内嵌式和外链的样式是得不到的
  • 设置宽度,高度,位置的属性类型是字符串,需要加上px
  • 复合属性转换成驼峰性
  • 在实际工作中,如果需要修改多条通过类名的方式,如果需要修改的样式只有1-2条直接使用style操作
  <script>
        // 工作中选择哪种方式
        // 获取元素
        var btn = my$("btn");
        var box = my$("box");
        // 给按钮添加点击事件
        btn.onclick = function () {
            // 1.更改类名的方法
            // box.className = "cls";
            // 2.通过元素对象的style属性设置
            box.style.width = "100px";
            box.style.height = "100px";
            box.style.backgroundColor = "blue";
            // 如果更改条数比较多,选择更改类名方式,如果更改属性比较少,则选择style方式
        };
    </script>

6.8 节点

节点属性
Nodetype 节点的类型,属性值为数字,表示不同节点类型,只读
1 元素节点
2 属性节点
3 文本节点

  • NodeName 节点的名称(标签名称),只读
  • NodeValue 节点值,返回或者是当前节点值,元素节点的nodeValue始终是null
    <div id="box"></div>
    <script>
        var box = document.getElementById("box");
        // 1.元素节点
        console.dir(box);
        // 属性节点获取
        var idNode = box.getAttributeNode("id");
        console.dir(idNode);
        idNode.nodeValue = "demo";
        
        // 文本节点
        var childNodes = box.childNodes;
        console.log(childNodes);
        childNodes[0].nodeValue = "box 1";
    </script>

节点关系

  • 父子节点常用属性

• childNodes ,获取一个节点所有子节点的实时的集合,集合是动态变化的,只读(数组)

• children ,返回一个节点所有的子元素节点集合,是一个动态更新的 HTML 元素集合,只读(不包含文本和属性节点)

• firstChild ,返回该节点的第一个子节点,没有返回 null。只读

• lastChild ,返回该节点的最后一个子节点,没有返回 null。只读

• parentNode 返回一个当前节点的父节点,如果没有这样的节点,比如说像这个节点是树结构的顶端或者没有插入一棵树中,这个属性返回 null。

• parentElement 返回当前节点的父元素节点,如果该元素没有父节点,或者父节点不是一个 DOM元素,则返回 null。

 var box = document.getElementById("box");
        // 获取子节点
        console.log(box.childNodes);//获取所有类型的子节点(会获取一些不需要的换行符号等)
        console.log(box.children);//获取所有元素类型的子节点,用的较多
        console.log(box.firstChild);//获取所有类型的子节点的第一个
        console.log(box.lastChild);//获取所有类型的子节点的最后一个
        console.log(box.lastElementChild);//获取所有元素类型的子节点的最后一个(用的多)
        // 获取父级
        console.log(box.parentNode);//获取父级的元素节点
        console.log(box.parentElement);
  • 兄弟节点关系
    • nextSibling ,返回与该节点同级的下一个节点,没有返回null。只读属性

    • previousSibling ,返回与该节点同级的上一个节点,没有返回null。只读属性

    • nextElementSibling ,返回与该节点同级的下一个元素节点,如果没有返回null。只读属性

    注意:nextElementSibling 和 previousElementSibling 有兼容性问题,IE9以后才支持。

  • 创建新节点
    • document.createElement("div") 创建元素节点
    • document.createAttribute("id") 创建属性节点
    • document.createTextNode("hello") 创建文本节点
    • parentNode.appendChild(child):将一个节点添加到指定父节点的子节点列表末尾。
    保存到变量中,方便使用.

// 创建新的节点
    var div = document.createElement("div");
    var cls = document.createAttribute("class");
    var txt = document.createTextNode("hello");
    // 创建的新的节点,是存储在内存中的,但是并没添加到 DOM 树上
    // 获取元素
    var box = my$("box");
    var p2 = my$("p2");
    box.appendChild(div);
    // 文本节点也可以添加到元素内部
    div.appendChild(txt);
    // 注意:自己创建的元素节点本身也是一个对象,也可以去添加一些新的属性和方法,这些操作将来在元素加载到 DOM 树中时,依旧保留

    // DOM 中原有的节点也可以传给 appendChild 的参数
    box.appendChild(p2);

节点操作

  • parentNode.replaceChild(newChild, oldChild):用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。

  • parentNode.insertBefore(newNode, referenceNode):在参考节点之前插入一个拥有指定父节点的子节点,
    referenceNode 必须设置,如果 referenceElement 为 null 则 newNode将被插入到子节点的末尾。

  • parentNode.removeChild(child):移除当前节点的一个子节点。这个子节点必须存在于当前节点中。

  • Node.cloneNode():克隆一个节点,并且可以选择是否克隆这个节点下的所有内容。参数为Boolean 布尔值,表示是否采用深度克隆,如果为 true,则该节点的所有后代节点也都会被克隆,如果为 false,则只克隆该节点本身,默认值为 true,节点下的内容会被克隆。
    • 注意:克隆时,标签上的属性和属性值也会被复制,写在标签行内的绑定事件可以被复制,但是通过 JavaScript 动态绑定的事件不会被复制。

<div id="box">
        <p>段落内容 1</p>
        <p id="p2">段落内容 2</p>
        <p>段落内容 3</p>
        <p>段落内容 4</p>
      </div>
      <script src="common.js"></script>
      <script>
        //   创建新节点
        var div = document.createElement("div");
        var cls = document.createAttribute("class");
        console.log(cls);
        var txt = document.createTextNode("hello");

        // 创建新的节点,是存储在内存中的,并没有放在 DOM树中
        div.appendChild(txt);
        // 获取元素
        var box = my$("box");
        var p2 = my$("p2");
        // 替换节点
        // box.replaceChild(div,p2);

        // 在某个指定子节点之前添加一个新的子节点
        box.insertBefore(div,p2);

        box.insertBefore(div,null);
        // 移除节点
        box.removeChild(p2);
        // 克隆元素box
        // 浅度克隆
        // var newBox = box.cloneNode(false);
        // 深度克隆
        var newBox = box.cloneNode(true);
        new box.id = "newBox";
        document.body.appendChild(newBox);

    </script>

节点判断

• Node.hasChildNodes():没有参数,返回一个 Boolean 布尔值,来表示该元素是否包含有子节点。
• Node.contains(child):返回一个 Boolean 布尔值,来表示传入的节点是否为该节点的后代节点。

 // 判断内部有子节点的方法有三种
    // 1.判断有没有子节点,不区分节点类型
    // console.log(box.hasChildNodes());
    // console.log(demo.hasChildNodes());
    // 2.判断节点内部第一个子节点是否不为空
    // console.log(box.firstChild !== null);
    // console.log(demo.firstChild !== null);
    // 3.判断子节点的数组对象的长度是否为0
    console.log(box.childNodes.length > 0);
    console.log(demo.childNodes.length > 0);

    // 补充子元素节点是否存在
    console.log(box.children.length > 0);
    console.log(demo.children.length > 0);
    // 判断节点内部是否有某个后代节点
    // console.log(box.contains(p2));

案例:

<h1>动态创建列表</h1>
    <div id="box">
      <!-- <ul>
        <li>刘备</li>
      </ul> -->
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var box = my$("box");
        // 创建一组数据
        var names = ["刘备","曹操","孙权","关羽"];
        // 添加ul元素
        var ul = document.createElement("ul");
        // 添加元素到box内部
        box.appendChild(ul);
        // 根据数组项向 li 中添加数据
        for (var i = 0 ; i < name.length ; i++) {
            // 每次生成一个新的 li 元素
            var li = document.createElement("li");
            // 向 ul 里添加 li
            ul.appendChild(li);
            // 给每个 li 元素添加内容
            li.innerText = names[i];
        }

6.9 事件流

事件流

存在捕获现象时,先捕获,在进行冒泡

  • addEventListener 第三参数:用来事件流的方向,参数是布尔值,false:事件冒泡类型; true:事件捕获类型。默认值是false
    三个阶段
    1. 事件捕获
    2. 事件执行
    3. 事件冒泡
  • addEventListener() 第三个参数为 false 时,事件冒泡
  • addEventListener() 第三个参数为 true 时,事件捕获
  • onclick 的方法类型:只能进行事件冒泡过程,没有捕获阶段
  • attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        // 获取元素
        var box1 = document.getElementById("box1");
        var box2 = document.getElementById("box2");
        var box3 = document.getElementById("box3");
        // 添加点击事件
        // addEventListener 有第三个参数,用来决定事件流的方向
        // 参数值是 布尔类型的值,false 表示事件冒泡过程,true 表示事件捕获过程
        // 参数默认值是 false
        // box1.addEventListener("click",function () {
        //     console.log(1);
        // },false);
        // box2.addEventListener("click",function () {
        //     console.log(2);
        // },false);
        // box3.addEventListener("click",function () {
        //     console.log(3);
        // },false);
        // box1.addEventListener("click",function () {
        //     console.log(this.id);
        // },true);
        // box2.addEventListener("click",function () {
        //     console.log(this.id);
        // },true);
        // box3.addEventListener("click",function () {
        //     console.log(this.id);
        // },true);

        // onclick 属性添加事件方法只有冒泡过程,没有捕获过程
        // attachEvent() 方法添加事件方法只有冒泡过程,没有捕获过程
        box1.onclick = function () {
            console.log(1);
        };
        box2.onclick = function () {
            console.log(2);
        };
        box3.onclick = function () {
            console.log(3);
        };

事件委托
利用事件冒泡,将子级事件委托给父级加载
同时需要利用事件函数的 e 参数,内部存储的是事件对象

   <ul id="list">
        <li>刘亦菲</li>
        <li>杨幂</li>
        <li>唐嫣</li>
        <li>赵丽颖</li>
        <li>刘诗诗</li>
    </ul>
    <script>
        // 让每个 li 被点击后,添加特殊背景色,其他的不添加
        // 以前思路:获取每个li标签,批量添加事件
        // 事件委托:可以将一些子级的公共类型的事件委托给他们的父级添加,在父级内部想办法找到真正触发事件的最底层的事件源
        // 获取元素
        var list = document.getElementById("list");
        var lis = list.children;
        // 给ul添加点击事件
        list.onclick = function () {
            // 在内部要想办法找到真正出发的事件 li 
            // 借用事件函数内部的一个参数 e ,e 是事件对象
            // 只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据
            // e.target 属性记录的就是真正触发事件的事件源
            // 排除其他
            for (var i = 0; i < lis.length; i++) {
                lis[i].style.backgroundColor = "";
            }
            e.target.style.backgroundColor = "pink";
        };
    </script>

事件对象
只要触发事件,就有一个对象,内部存储了事件相关数据

  • e.eventPhase 查看事件触发时所处的阶段
  • e.target 用于获取触发事件的元素
  • e.srcElement 用于获取触发事件的元素,低版本浏览器使用
  • e.currentTarget 用于获取绑定事件的事件源元素
    e在低版本浏览器中有兼容问题,低版本浏览器使用的是window.event
            // 获取真正出发事件的元素,兼容写法
            var target = e.target || e.srcElement;
            // 事件对象兼容
            e = e || window.event;


  • e.type 获取事件类型
  • e.clientX/e.clientY 所有浏览器都支持,鼠标距离浏览器窗口左上角的距离
  • e.pageX/e.pageY IE8 以前不支持,鼠标距离整个HTML页面左上顶点的距离
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        #box1{
            width: 200px;
            height: 200px;
            background-color: yellowgreen;
        }
    </style>
</head>
<body>
    <div id="box1"></div>
    <script>
        // 获取元素
        var box1 = document.getElementById("box1");

        // e.type 属性获取事件类型
        // box1.onclick = function (e) {
        //     // 事件对象兼容
        //     e = e || window.event;
        //     // 触发的事件类型
        //     console.log(e.type);
        // };

        // 更多时候可能给同一个元素对象添加不同的事件类型,对应执行的事件函数内部的代码 不同
        // box1.onmouseover = function () {
        //     box1.style.backgroundColor = "skyblue";
        // };
        // box1.onmouseout = function () {
        //     box1.style.backgroundColor = "yellowgreen";
        // };
        // 可以将 所有给一个元素绑定的事件函数写在一个 函数内,通过函数内部的 e.type 判断走不同的分支
        // box1.onmouseover = fn;
        // box1.onmouseout = fn;
        // // 避免添加多个函数,占用更多的内存
        // function fn (e) {
        //     e = e || window.event;
        //     switch (e.type) {
        //         case "mouseover":
        //             box1.style.backgroundColor = "pink";
        //             break;
        //         case "mouseout":
        //             box1.style.backgroundColor = "skyblue";
        //             break;
        //     }
        // }
        // 事件对象中一些获取尺寸的属性
        box1.onclick = function (e) {
            // client系列:客户端尺寸,点击的点参考浏览器窗口左上角的距离
            console.log(e.clientX);
            console.log(e.clientY);
            // page 系列:html 页面尺寸,点击的点参考html 文档左上角距离
            console.log(e.pageX);
            console.log(e.pageY);
        }

取消默认行为和组织时间传播的方式

  • e.preventDefault() 取消默认行为
  • e.returnValue 取消默认行为,低版本浏览器使用
  • e.stopPropagation(); 阻止冒泡,标准方式
  • e.cancelBubble = true; 阻止冒泡,IE 低版本,标准中已废弃
    <a id="link" href="52_图片跟随鼠标移动效果.html">点击</a>
    <script>
         var link = document.getElementById('link');
         link.onclick = function (e) {
            e = e || window.event;
            alert("hello");
            // 普通的方式阻止默认行为
            return false;
            // DOM 方法
            e.preventDefault();
            // 低版本浏览器需要使用一个对象的属性
            e.returnValue = false;
         }
    </script>

   <div id="box1">
        <div id="box2">
          <div id="box3">
          </div>
        </div>
      </div>
    <script>
        // 事件冒泡
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');

        var array = [box1, box2, box3];

        for (var i = 0; i < array.length; i++) {
            var box = array[i];
            box.onclick = function (e) {
              e = e || window.event;
              console.log(this.id);
              // 阻止事件冒泡
              // e.stopPropagation();
              // 低版本浏览器使用 属性
              e.cancelBubble = true;
            }
        }

6.10 DOM特效

偏移量属性
• offsetParent 偏移参考父级,距离自己最近的有定位的父级,如果都没有定位参考body(html)
• offsetLeft/offsetTop 偏移位置
• offsetWidth/offsetHeight 偏移大小(border及以内的宽高)

偏移量
 <script>
              // 获取元素
              var child = document.getElementById("child");
              // 元素天生就认识自己的偏移参考父级
              // console.log(child.offsetParent);
              
              // 偏移位置
              // console.log(child.offsetLeft);
              // console.log(child.offsetTop);
              
              // 偏移大小
              console.log(child.offsetWidth);
              console.log(child.offsetHeight);
      </script>

客户端大小
• client 系列没有参考父级元素。
• clientLeft/clientTop 边框区域尺寸,不常用
• clientWidth/clientHeight 边框内部大小

客户端大小

滚动偏移属性
• scrollLeft/scrollTop 盒子内部滚动出去的尺寸
• scrollWidth/scrollHeight 盒子内容的宽度和高度

滚动偏移
 var box = document.getElementById("box");
        // 滚动便宜位置和大小
        // 滚动条滚动事件
        box.onscroll = function () {
            console.log(box.scrollLeft);
            console.log(box.scrollTop);
        }

二、BOM 浏览器对象模型

  • 提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。
  • BOM 由多个对象组成,其中代表浏览器窗口的 Window对象是 BOM 的顶层对象,其他对象都是该对象的子对象。
    -我们在浏览器中的一些操作都可以使用BOM的方式进行编程处理,比如:刷新浏览器、后退、前进、在浏览器中输入URL等。

1.Window对象

window 是浏览器的顶级对象,当调用 window 下的属性和方法时,可以省略 window。
有两个特殊的属性:window.name(会在原来的name属性上赋值)和window.top (只读的,不能后期更改)

2.对话框

Alert()
Prompt()
Confirm()

 // 警示框
    btn1.onclick = function () {
      alert("hello");
    };

    // 提示框
    btn2.onclick = function () {
      var num = prompt("请输入一个数字",12);
      console.log(num);
    };

    // 让用户确认或者选择的对话框
    // confirm 方法有返回值,根据按钮点击情况,如果返回确定,返回true,点击取消返回false
    btn.onclick = function () {
        confirm("请问,你确定删除这条数据吗?");
    };

3.加载事件

  • Onload事件
    window加载完毕才会执行的事件函数
    Window对象加载完毕:指的是html结构加载完,并引入外部资源(js、css、img、视频)也加载完毕。
    一个页面只能有一个window.onload事件

4.延时器:

Window对象的方法,类似于定时炸弹

  • 功能:指定时间后执行函数
  • window.setTimeout(func,time);
    • 参数1:执行函数,可以匿名,可以函数名引用,不要加括号
    • 参数2:时间,毫秒为单位
// 延时器
        // 异步语句
        var timeout = window.setTimeout(function () {
            console.log("hello");
        },2000);

5.定时器

Window对象方法,,每隔一段时间执行一次

  • 功能:每隔指定时间,周期性执行
  • window.setInterval(func,interval);
    • 参数1:执行函数,可以匿名或者函数引用
    • 参数2:时间间隔,毫秒单位
      清除定时器
  • window.clearInterval(timer);
    • 参数:指定的定时器变量名引用。
      • 功能:清除指定的定时器。
      • 注意:清除的定时器需要存储到一个变量中,便于后期清除调用。
<!-- 开启定时器: 每隔 0.5 秒输出一次 i, 并且让 i 每次自加 -->
    <script>
        var i = 1;
        // 定时器也是异步加载
        // 程序执行定时器代码部分相当于开启定时器,不需要其他操作
        // 第一次执行函数时,是在第一个时间间隔之后
        // 清除定时器,在定义的时候必须存到一个变量中
        var timer = window.setInterval(function () {
            console.log(i++);
        },500);
        // 清除定时器
        window.clearTimeout(timer);
    </script>

6.简单运动

通过定时器,实现每隔一个极短的时间(50-100 毫秒左右),执行函数,函数内部让运动的属性值发生变化。
拉终停表案例
设表先关案例请查阅笔记,此处不展示。

7.location对象

location 对象是 window 对象下的一个属性,使用的时候可以省略 window 对象
• location 可以获取或者设置浏览器地址栏的 URL
• 使用 chrome 的控制台查看
• 查 MDN:https://developer.mozilla.org/zh-CN/

        var btn = document.getElementById("btn");
        btn.onclick = function () {
        //     // 输出url地址
        //     console.log(location.href);
        //     // 重新赋值
        //     location.href = "http://www.baidu.com";
        // 
        // assign委派
            // assign() 方法作用与href属性相同,可以设置页面跳转地址
            // location.assign("http://www.lagou.com");
            
            
            // replace替换
            // 替换掉地址栏中当前网址,不记录历史网址
            // location.replace("http://www.lagou.com");

            // reload重新加载
            // 类似于键盘 f5功能,类似于false效果,ctrl+f5强制刷新,从服务器获取页面,相当于true
            // 参数:true强制从服务器获取页面,false从浏览器换粗又网页的话,直接从缓存获取
            location.reload(true);

        };
location对象属性 返回值
location.href 获取或设置url
location.host 返回主机域名
location.prot 返回端口号 如没有返回空字符串
location.pathname 返回路径
location.search 返回参数
location.hash 返回片段 #后面的内容 常见于链接,锚点
location.assgin() 方法 实现跳转 可以重定向 计入浏览历史
location.replace() 方法 实现跳转 不计入历史
location.reload() 方法 重新加载页面 参数为true是强制刷新

8.history对象

history 对象是 window 对象下的一个属性,使用的时候可以省略 window 对象

history对象方法 作用
history.back() 后退
history.forward() 前进
history.go(参数) 前进后退功能 1前进 -1后退

9.url 对象

统一资源定位符 (Uniform Resource Locator, URL)

URL的组成:scheme://host:port/path?query#fragment

例如:http://www.lagou.com:80/a/b/index.html?name=zs&age=18#bottom

• scheme:通信协议,常用的http,ftp,maito等

• host:主机,服务器(计算机)域名系统 (DNS) 主机名或 IP 地址。

• port:端口号,整数,可选,省略时使用方案的默认端口,如http的默认端口为80。

• path:路径,由零或多个'/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。

• query:查询,可选,用于给动态网页传递参数,可有多个参数,用'&'符号隔开,每个参数

的名和值用'='符号隔开。例如:name=zs

• fragment:信息片断,字符串,锚点.

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

推荐阅读更多精彩内容