WebAPI入门指南:DOM和BOM的基础知识

WebAPI

1.什么是WebAPI

​ WebAPI能够让不同的应用程序和系统之间进行数据交互,就像人们通过电话交流一样,让不同的系统之间能够相互理解和协作。Web APIs是JS的应用,大量使用JS语法做交互效果

WebAPI :WebAPI是浏览器提供一套操作浏览器功能和页面元素的API(BOMDOM)。

2.为什么要学习WebAPI

​ 学习WebAPI可以让我们了解如何使用网络接口来访问和处理远程数据,提高Web开发的效率和灵活性,为构建更好的Web应用程序提供技术支持。

在这里我们主要针对浏览器学习常用的API,主要针对浏览器做交互效果。

3.MDN

​ MDN是Mozilla开发者网络的缩写,是一个提供Web开发文档的网站。MDN的目标是帮助开发者更好地理解和使用Web技术,提高Web开发的质量和效率。

MDN详细API地址: https://developer.mozilla.org/zh-CN/docs/Web/API

一.DOM

1.DOM简介

1.1什么是DOM

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。

​ W3C已经定义好了一系列的DOM接口,通过DOM接口可以改变网页的内容、结构和样式。

1.2DOM树

文档:一个页面就是一个文档,DOM使用document来表示

元素:页面中的所有标签都是元素,DOM中使用element来表示

节点:网页中的所有内容都是节点(包括标签属性文本注释等)

2.DOM获取元素

​ DOM在我们的实际开发中主要用来操作元素,操作页面元素首先要使用document.的方式。获取到我们获取页面中的元素可以使用以下几种方式:

  • 根据元素ID获取
  • 根据标签名获取
  • 通过HTML5新增的方法获取
  • 特殊元素的获取

示例:

<div class="box" id="time">2023-3-23</div>
1.根据ID名获取

getElementById('id')

		var timer = document.getElementById('time');    
		console.log(timer);             
		console.log(typeof timer);      //   object     返回的是一个元素对象
		console.dir(timer);
  • 通过getElementById(‘id’)的方式获取到id为time的div元素对象
  • 可以看到getElementById(‘id’)返回的是一个对象object
  • 可以使用console.dir()打印我们返回的元素对象,更好的查看里面的属性和方法

示例:

	<ul>
        <li>知否知否,应是绿肥红瘦11</li>
        <li>知否知否,应是绿肥红瘦22</li>
    </ul>

    <ol id="ol">
        <li>东临碣石,以观沧海1</li>
        <li>东临碣石,以观沧海2</li>
    </ol>

    <div>
        <p>只有一个p</p>
    </div>
2.根据标签名获取

getElementsByTagName('标签名')

		var lis = document.getElementsByTagName('li');
		console.log(lis);       // [li,li]
        console.log(lis[0]);	// <li>知否知否,应是绿肥红瘦1</li>
  • getElementsByTagName(‘标签名’):获取指定标签名的对象集合(返回的是元素对象集合)
  • 获取到的元素对象集合是以伪数组的形式进行存储的
  • 如果页面中没有这个元素,返回的是一个空的伪数组[]
  • 以上getElementsByTagName(‘li’)表示获取到所有的li元素
  • 在此基础上我们还可以通过某个元素(父元素)内部获取所有指定标签名的子元素,如我们获取ol中的li:

​ 方式1:

        var ol = document.getElementsByTagName('ol');   
        var lis2 = ol[0].getElementsByTagName('li');
		console.log(lis2)		// [li li]
  • 先获取到父元素ol,再通过ol[索引号].getElementsByTagName('li')
  • ol必须要有索引才能获取到里面的子元素(因为getElementsByTagName()返回的是伪数组形式的)

​ 方式2:

		var ol2 = document.getElementById('ol');
        var lis3 = ol2.getElementsByTagName('li');
        console.log(lis3)   // [li,li]
  • ol加上id,然后父元素通过id获取(常用)
3.H5新增的方式获取

示例:

	<div class="box">盒子1</div>
    <div class="box">盒子2</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>

(1)getElementsByClassName('类名')

		var boxs = document.getElementsByClassName('box');
        console.log(boxs);  // [div.box,div.box]
  • getElementsByClassName('类名') :根据类名返回元素对象集合
  • 以上根据类名(box)返回了页面中的所有box元素

(2)querySelector('选择器')

		var firstBox = document.querySelector('.box');     // 类选择器
        console.log(firstBox);		// [div.box]			
  • querySelector('选择器'): 根据指定选择器返回第一个元素对象
  • 以上根据类选择器(.box)返回了第一个类名为box的元素

(3)querySelectorAll('选择器')

	 	var AllBox = document.querySelectorAll('.box');
        console.log(AllBox);    // [div.box,div.box] 
  • querySelectorAll('选择器'): 根据指定选择器返回所有元素对象集合
  • 以上根据类选择器(.box)返回了所有类名为box的元素
4.特殊元素获取

(1)document.body

		var bodyElm = document.body;
        console.log(bodyElm);
  • document.body: 获取body元素对象

  • 以上返回了页面中的body元素

(2)document.documentElement

		var htmlElm = document.documentElement;
        console.log(htmlElm);
  • document.documentElement: 获取html元素对象

  • 以上返回了页面中的html元素

3.DOM事件

​ 网页中的每个元素都可以产生某些可以触发JavaScript的事件。当用户与网页交互时,浏览器会自动触发相应的事件,我们可以使用JavaScript代码来监听这些事件,并根据需要执行相应的操作。

​ 常见的DOM事件包括鼠标事件键盘事件表单事件窗口事件等。

事件的三要素:1.事件源 2.注册事件(绑定事件) 3.事件处理程序

1.常见的鼠标事件

鼠标事件触发条件
onclick鼠标点击左键触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onfocus获得鼠标焦点触发
onblur失去鼠标焦点触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发
ondblclick鼠标双击触发

2.执行事件的步骤

<div>666</div>
		// 1.获取事件源
        var div = document.querySelector('div');

        // 2.绑定事件(注册事件)
        // div.onclick

        // 3.添加事件处理程序
        div.onclick = function () {
            console.log('我被选中了!');
        }
  • 以上通过获取事件源(div)、注册事件(div.onclick)、事件处理函数(function())这三个步骤,当点击div盒子时,控制台就输出了console.log('我被选中了!')的代码

4.操作元素

​ JavaScript的DOM操作可以改变网页内容结构样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。

示例:

<button class="btn">222</button>
1.修改元素内容

1.element.innerText

		var btn = document.querySelector('.btn')
		btn.onclick = function () {     
            div.innerText = '666';
        }
  • element.innerText可以修改元素的内容

  • 以上当点击了按钮时,<button>里的内容修改为了666

2.element.innerHTML

		var btn = document.querySelector('.btn')
		btn.onclick = function () {     
            div.innerHTML = '666';
        }
  • element.innerHTML也可以修改元素内容

innerText和innerHTML(常用)的区别:

相同点:

都能改变元素的内容,都能获取元素里的内容(是可读写的)

不同点:

1.innerText不能识别html标签 非标准,innderHTML能识别html标签W3C标准

2.innerText去除空格、换行,而innerHTML保留空格、换行

示例:

	<div></div>
    <p>
        pan很帅
        <span>of course</span>
    </p>
		var div = document.querySelector('div');
		div.innerText = '<strong>今天是</strong>:2023-3-24';	// 字体不会加粗
		div.innerHTML = '<strong>今天是</strong>:2023-3-24';	// 字体会加粗

		var p = document.querySelector('p');
        console.log(p.innerText);		
        console.log(p.innerHTML);
  • 以上使用innerText不会将<strong>标签的内容加粗,不能识别html标签,而innerHTML识别html标签
  • innerText获取到<p>中的文本去除了空格、换行,而innerHTML保留空格、换行
2.修改元素属性

​ DOM操作可以修改网页中元素的属性,如:src,href,id,alt,title等,使用element.属性的方式对元素进行修改。

示例:

		div {
            width: 320px;
            height: 220px;
        }

        div img {
            width: 100%;
            height: 100%;
        }

		<button id="hg">胡歌</button>
   		<button id="zly">赵丽颖</button> <br>
    	<div>
        	<img src="images/hg.jpg" alt="" title="">
    	</div>
		var hg = document.getElementById('hg');
        var zly = document.getElementById('zly');
        var img = document.querySelector('img');
        
        hg.onclick = function () {
            img.src = 'images/hg.jpg';
            img.title = '胡歌';
        }

        zly.onclick = function () {
            img.src = 'images/zly.jpg';
            img.title = '赵丽颖';
        }

  • 以上通过img.src,img.title的方式对img的src属性、title属性进行了修改。当点击了按钮时,就可以实现图片和标题的切换
3.修改表单属性

​ DOM可以操作表单的属性,如:type,value,checked,selected,disabled等。通过element.表单属性修改表单属性。

示例:

	<button>按钮</button>
    <input type="text" value="8-8-8">
		var btn = document.querySelector('button');
        var ipt = document.querySelector('input');
        btn.onclick = function () {
            ipt.value = '被点击啦';            
            // btn.disabled = true;              
            this.disabled = true;          
        }
  • 以上修改表单里的内容使用到了value属性

  • 使用disabled属性可以使某个表单要被禁用,不能再点击

  • 使用this,this指向的是事件函数的调用者(btn)

innerHTML修改元素的内容只能用于普通盒子例如div,p..等,而要修改表单元素的内容,使用到的是value属性。

4.修改样式属性

​ 通过操作DOM,我们可以修改元素的大小颜色位置等样式。

​ 修改元素的样式属性有: 1.element.style(行内样式操作) 2. element.className(类名样式操作)

示例:

		div {
            width: 200px;
            height: 200px;
            background-color: pink;
        }

1.element.style

			var div = document.querySelector('div');
        	div.onclick = function () {
            
            this.style.backgroundColor = 'orange';
            this.style.width = '300px';
        }
  • 以上使用element.style的方式修改了元素div的backgroundColor(背景颜色),width(宽度)
  • 在js修改style样式操作采用的是驼峰命名法
  • js修改style样式操作,产生的是行内样式,权重要比css权重高

2.element.className

<div class="first">文本</div>
		var div = document.querySelector('div');
        div.onclick = function () {
		   this.className = 'first change';		// 两个类名
        }
  • 以上使用了element.className的方式修改样式,是以修改类名的方式来修改样式

  • 我们可以在css中新定义一个.change类名,然后写上新的样式,在js中使用className更改元素的类名

  • className会直接更改元素的类名,会覆盖原先的类名,如果我们想保留原先类名,可以以多类名的方式

  • 如果样式修改比较多,可以采取element.className

5.自定义属性操作

​ 当我们要获取或设置元素的属性值时可以有两种方式:

​ 1.element.属性 2.element.getAttribute()

element.属性的方式是用于内置属性,而element.getAttribute()的方式主要是针对自定义的属性

示例:

<div id="demo" index="1" class="one" remov="00"></div>

1.获取元素的属性值

(1)element.属性

console.log(div.id);		// id是内置属性

(2)element.getAttribute('属性')

console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));		// index是自定义属性

2.设置元素的属性值

(1)element.属性 = 值

div.id = 'text';
div.className = 'nav';

(2)element.setAttribute('属性','值')

div.setAttribute('index', 2);
div.setAttribute('class', 'nav2');

(3).删除属性值

removeAttribute('属性')

div.removeAttribute('remov');
6.H5自定义属性

​ 在H5自定义属性中,定义属性我们统一设置成以data-开头,如data-index

​ H5新增了获取自定义属性的方式:element.dataset.属性名element.dataset['属性名']

示例:

<div getTime="20" data-time="10" data-index="2" data-list-name="pan"></div>

1.获取自定义属性

(1)element.getAttribute('属性名')(兼容性获取)

var div = document.querySelector('div');	
console.log(div.getAttribute('getTime'));	// 20
console.log(div.getAttribute('data-time'))	// 10
  • element.getAttribute(‘属性名’)获取属性时,属性名就是完整的属性名

(2) element.dataset.属性名(H5新增方式获取)

var div = document.querySelector('div');
console.log(div.dataset.time);			// 10
console.log(div.dataset['index']);		// 2
  • 使用dateset只能获得以data开头的属性

dataset是一个集合,里面存放了所有以data-开头的自定义属性:

console.log(div.dataset);	// {time: '10', index: '2'} 

若自定义属性名字过长,有多个-连接,使用dataset获取要驼峰命名:

console.log(div.dataset.listName);	// pan

5.节点操作

1.节点概述

​ 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node表示。

​ 节点至少拥有的三个基本属性:nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)。

  • 元素节点 nodeTyoe 为1
  • 属性节点 nodeTyoe 为2
  • 文本节点 nodeTyoe 为=3(文本节点包含文字、空格、换行等)

2.为什么要使用到节点

  • 利用DOM提供的方法获取元素(document.getElementById()等) 逻辑性不强、繁琐。
  • 利用节点层次关系获取元素(父子兄弟节点获取元素)逻辑性强,但是兼容性稍差,这两种方式都可以获取元素,节点操作更简单
1.父节点操作

示例:

    <div class="father">
        <span class="son"></span>
    </div>

node.node.parentNode

var son = document.querySelector('.son');
console.log(son.parentNode);
  • 父节点操作使用node.parentNode方式,得到的是最近的父级元素

  • son.parentNode表示获取到父元素节点

  • 如果找不到父节点就返回null

2.子节点操作

示例:

<ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>

1.获取子节点

(1) parentNode.childNodes()

var ul = document.querySelector('ul');
console.log(ul.childNodes)
  • ul.childNodes()表示ul获取到所有的子节点(包括元素节点、文本节点等)

(2) parentNode.children()

var ul = document.querySelector('ul');
console.log(ul.childNodes)
  • ul.children()ul表示获取所有子节点(得到的是元素节点)

常用的是parentNode.children()获取子节点,因为一般我们主要是对元素节点进行操作。

2.获取第一个子元素节点和最后一个子元素节点

(1) parentNode.firstChild parentNode.lastChild

var ul = document.querySelector('ul');
console.log(ul.firstChild);
console.log(ul.lastChild);
  • ul.firstChild,ul.lastChild表示ul获取到第一个/最后一个节点(包含了文本节点、元素节点等)

(2) parentNode.firstElementChild parentNode.lastElementChild

var ul = document.querySelector('ul');
console.log(ul.firstElementChild);
console.log(ul.lastElementChild);
  • ul.firstElementChild,ul.lastElementChild表示获取到第一个/最后一个的子元素节点(但是有兼容性问题,要使用-ie9以上版本浏览器)

(3)parentNode.childen[]

var ul = document.querySelector('ul');
console.log(ul.children[0]); 
console.log(ul.children[ul.children.length - 1]);
  • ul.children[0]表示ul元素获取第一个子节点(元素节点)
  • ul.children[ul.children.length - 1]表示ul元素获取最后一个子节点(元素节点)
3.兄弟节点操作

示例:

<div>我是div</div>
<span>我是span</span>

1.获取兄弟节点

(1) node.nextSibling node.previousSibling

var div = document.querySelector('div');
console.log(div.nextSibling);		// #text
console.log(div.previousSibling);	// #text
  • div.nextSibling,div.previousSibling表示div元素获取上/下一个兄弟节点(包含文本节点等…)

(2) node.nextElementSibling node.previousElementSibling

var div = document.querySelector('div');
console.log(div.nextElementSibling);
console.log(div.previousElementSibling)
  • div.nextElementSibling div.previousElementSibling表示div获取上/下一个兄弟节点(得到的是元素节点)
  • 但是容易有兼容性问题,-ie9以上才支持

解决方式: 自己封装一个兼容性函数

function getNextElementSibling(element) {
            var el = element;
            while (el = el.nextSibling) {
                if (el.nodeType === 1) {	// 表示得到的是元素节点
                    return el;
                }
            }
            return null;
        }
function getPreviousElementSibling(element) {
            var el = element;
            while (el = el.previousSibling) { // 表示得到的是元素节点
                if (el.nodeType === 1) {
                    return el;
                }
            }
            return null;
        }
4.创建和添加节点

页面中想要添加一个元素,需要: 1.创建节点 2.添加节点

示例:

	<ul>
        <li>123</li>
    </ul>

(1) 创建节点

document.createElement('标签名')

var list = document.createElement('li');
  • document.createElement(‘li’)创建了一个li节点(元素)

(2)添加节点

node.appendChild(child)

var ul = document.querySelector('ul');
ul.appendChild(list);
  • ul.appendChild(list)表示在后面追加list节点

node.insertBefore(child,指定元素)

ul.insertBefore(list2, ul.children[0]);
  • ul.insertBefore(list2, ul.children[0])表示在第一个孩子节点前添加节点
5.删除和克隆节点

(1)删除节点

node.removeChild(child)

ul.removeChild(ul.children[0]);
  • ul.removeChild(ul.children[0])表示ul删除第一个子节点(元素节点)

(2)克隆节点

node.cloneNode() 浅拷贝

var list = ul.children[0].cloneNode();
  • ul.children[0].cloneNode()表示ul拷贝第一个子节点(浅拷贝)
  • node.cloneNode()参数为空或为false时,表示浅拷贝
  • 浅拷贝只复制标签本身,不复制内容(内容所有包括子节点等等)

node.cloneNode(true) 深拷贝

var list = ul.children[0].cloneNode(true);
  • ul.children[0].cloneNode(true)表示ul拷贝第一个子节点(深拷贝)
  • node.cloneNode() 参数为true时,表示深拷贝
  • 深拷贝会复制节点及内容,包括里面的所有子节点等

6.事件高级

1.注册事件的两种方式

​ 注册事件(绑定事件)时,有这两种方式: 1.·传统方式 2.方法监听注册事件

示例:

	<button>传统方式注册事件</button>
    <button>方法监听注册事件</button>
    <button>ie9以前的attachEvent</button>

1.传统注册事件

element.onclick

 		// 1.获取事件源
		var btns = document.querySelectorAll('button');
		// 2.注册事件 3.事件处理函数 
        btns[0].onclick = function () {

            alert('22');
        }

        btns[0].onclick = function () {
            alert('33');			// btns[0]执行此onclick
        }
  • 传统方式注册事件具有唯一性

  • 唯一性:同一个元素同一个事件只能设置一个处理函数,后面注册的处理函数覆盖之前注册的处理函数)

2.方法监听注册事件

eventTarget.addEventListener(type,listenner[,useCaptrue])

		btns[1].addEventListener('click', function () {

            alert('22');
        })

        btns[1].addEventListener('click', function () {

            alert('33');
        })
  • type: 事件类型字符串,比如click,mouseover,没有on前缀
  • listener: 事件监听函数,事件发生时,会调用该函数
  • useCapture: 可选参数,是一个布尔值,默认是false
  • addEventListener()注册事件同一个元素,同一个事件可以添加多个监听器,ie9以上支持该方法(常用)

attachEvent(EventNameWithOn,callback)

		btns[2].attachEvent('onclick', function () {
        alert('44');
  • EventNameWithOn: 事件类型字符串,有on前缀
  • callback: 回调函数
  • attachEvent():注册事件是ie9以前的版本,不常用了

如果可能存在不兼容性的浏览器版本时,需要注册事件兼容性解决方案:

		function addEventListener(Element, eventName, fn) {
            // 判断当前浏览器是否支持 addEventListener方法
            if (element.addEventListener) {
                element.addEventListener(eventName, fn);
            } else if (element.attachEvent) {
                element.attachEvent('on' + eventName, fn);
            } else {
                element['on' + eventName] = fn;
            }
        }
2.删除事件的两种方式

​ 删除(解绑事件)时,有这两种方式: 1.传统删除事件 2.方法监听删除事件

示例:

	<style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>

	<div>1</div>
    <div>2</div>
    <div>3</div>

1.传统删除事件

div.onclick = null

		var div = document.querySelectorAll('div');
        div[0].onclick = function () {

            alert(11);
            div.onclick = null;
        }

2.方法监听删除事件

removeEventListener()

		div[1].addEventListener('click', fn);

        function fn() {
            alert(22);
            div[1].removeEventListener('click', fn);
        }
  • removeEventListener()支持ie9以上版本浏览器(常用)

detachEvent()

		div[2].attachEvent('onclick', fn2);
        function fn2() {
            alert(33);
            div[2].detachEvent('onclick', fn2);
  • detachEvent()为了照顾低版本浏览器(不常用)

如果可能存在不兼容性的浏览器版本时,需要解绑事件兼容性解决方案:

		function removeEventListener(element, eventName, fn) {
            if (element.removeEventListener) {
                element.removeEventListener(eventName, fn);
            } else if (element.detachEvent) {
                element.detachEvent('on' + eventName, fn);
            } else {
                element['on' + eventName] = null;
            }
3.事件流

​ DOM事件流:事件发生会在元素节点之间按照特定的顺序传播.这个传播过程即DOM事件流

​ DOM事件流三阶段: 1.捕获阶段 2.当前目标阶段 3.冒泡阶段

示例:

	<style>
        div {
            margin: 200px auto;
        }

        .father {
            position: relative;
            width: 300px;
            height: 300px;
            background-color: pink;
        }

        .son {
            position: absolute;
            width: 200px;
            height: 200px;
            top: 50%;
            left: 50%;
            margin-left: -100px;
            margin-top: -100px;
            background-color: purple;
        }
    </style>
    
    <div class="father">
        <div class="son"></div>
    </div>
// 捕获阶段
        var son = document.querySelector('.son');
        son.addEventListener('click', function () {
            alert('son');
        }, true)

        var father = document.querySelector('.father');
        father.addEventListener('click', function () {
            alert('father');
        }, true)

// 冒泡阶段
		var son = document.querySelector('.son');
        son.addEventListener('click', function () {
            alert('son');
        }, false)

        var father = document.querySelector('.father');
        father.addEventListener('click', function () {
            alert('father');
        }, false)
  • 如果addEventListener第三个参数是true ,则处于捕获阶段: document -> html -> body -> father -> son

  • 如果addEventListener第三个参数是false 则处于冒泡阶段: son -> father -> body -> html -> document(实际开发中更关注事件冒泡)

小结:

  • js代码只能执行捕获或者冒泡中的其中一个
  • onclick和attachment()只能获得冒泡阶段
  • 捕获/冒泡阶段 addEventListener(type,listenner[,useCaptrue]) 第三个参数useCaptrue为true(捕获)/false(冒泡)
4.事件对象

​ 当事件发生后,跟事件相关的一系列信息数据的集合都会放在这个对象里面,这个对象就是event,它有很多属性和方法。

示例:

	<style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
// 获取事件对象e

		// 传统方式
		div.onclick = function (e) {
            console.log(e);

		// 事件监听方式
		var div = document.querySelector('div');
		div.addEventListener('click', function (e) {
            console.log(e);
        })
  • event就是一个事件对象,写到我们的侦听函数中,作为形参
  • 事件对象有了事件才会存在,它是系统自定给我们创建的,我们不需要传递实参
  • 事件对象是一系列相关数据的集合
  • 事件对象我们可以自己命名,如event,evt,e等

如果可是低版本浏览器或者可能存在不兼容性的浏览器版本时:

		div.onclick = function (e) {
            //  ie678 获取 照顾低版本浏览器
            console.log(window.e);  
            // 兼容性写法
            e = e || window.event       
5.常见事件对象的属性和方法
事件对象属性方法说明
e.target返回触发事件的对象(标准)
e.srcElement返回触发事件的对象(照顾低版本浏览器 ie9以下)
e.type返回事件的类型
e.preventDefault()阻止默认事件(方法 如不让链接跳转 标准)
e.returnValue阻止默认事件(属性 照顾低版本浏览器 ie9以下)
e.stopPropagation()阻止冒泡(方法 标准)
e.cancelBubble阻止冒泡(属性 照顾低版本浏览器 ie9以下 )

示例:


    <div>盒子</div>
    <ul>
        <li>li one</li>
        <li>li two</li>
        <li>li three</li>
    </ul>

1.返回触发事件的对象

e.target

		var div = document.querySelector('div');
        div.addEventListener('click', function (e) {

            console.log(e.target);		
            console.log(this);
        })

		var ul = document.querySelector('ul');
        ul.addEventListener('click', function (e) {

            console.log(e.target);		//  li  触发事件
            console.log(this);			//  ul  注册事件
  • e.target返回的是li,li是触发事件的对象(元素)
  • this返回的是ul,ul是注册事件的对象(元素)

e.srcElement

console.log(e.currentTarget);	
  • e.srcElement为了照顾低版本浏览器

如果可能遇到兼容性问题,使用兼容性解决方案:

// 兼容性写法
		div.onclick = function (e) {

            e = e || window.event;
            var target = e.target || e.srcElement;
            console.log(target);

和this很像的属性: currentTarget

console.log(e.currentTarget);
  • currentTarget不识别低版本浏览器,this最常用

2.获取事件类型

示例:

	<div>123</div<div>123</div>

e.type

		var div = document.querySelector('div');
        div.addEventListener('click', fun);
        div.addEventListener('mouseover', fun);
        div.addEventListener('mouseout', fn);
        function fun(e) {
            console.log(e.type);    
        }
  • e.type能获取到实际的类型如: click,mouseover,mouseout

3.阻止默认行为

示例:

	<a href="www.baidu.com">百度</a>
    <form action="www.baidu.com">
        <input type="submit" value="提交" name="sub" id="">
    </form>

(1)e.preventDefault()

 		var a = document.querySelector('a');
        a.addEventListener('click', fn);
        function fn(e) {

            console.log(e.preventDefault());  // dom标准写法
        }
  • e.preventDefault()阻止默认行为,链接a不能跳转

(2)e.returnValue

		a.onclick = function (e) {
			console.log(e.returnValue);
            
		}	
  • e.returnValue为了照顾低版本浏览器

return false也能阻止默认行为

缺点: return终止函数,不能继续执行后面的代码了

4.阻止事件冒泡

​ 事件冒泡的本身特性会带来坏处,也会带来好处,当冒泡具有坏处时,我们可以灵活的使用阻止冒泡。

示例:

	<div class="father">
        <div class="son"></div>
    </div>

(1) e.stopPropagation()

 var son = document.querySelector('.son');
        son.addEventListener('click', function (e) {
            alert('son');
            e.stopPropagation();        // dom 标准
        }, false)
  • e.stopPropagation()阻止事件冒泡,son元素的事件不能向上层father冒泡

(2)e.cancelBubble = true

		var son = document.querySelector('.son');
        son.addEventListener('click', function (e) {
            alert('son');
            e.cancelBubble = true;        
		}, false)
  • e.cancelBubble = true阻止冒泡事件照顾的是低版本浏览器

如果可能存在有兼容性问题时,解决兼容性方案:

		if (e && e.stopPropagation()) {
                e.stopPropagation()
            } else {
                window.event.cancelBubble = true;
            }

5.事件委托

​ 事件委托原理: 给父节点添加侦听器,利用事件冒泡影响每一个子节点。

示例:

	ul>
        <li>知否知否,应是绿肥红瘦</li>
        <li>知否知否,应是绿肥红瘦</li>
        <li>知否知否,应是绿肥红瘦</li>
        <li>知否知否,应是绿肥红瘦</li>
    </ul>

		var ul = document.querySelector('ul');
        ul.addEventListener('click', function (e) {
            // alert('yeyeye~');
            e.target.style.backgroundColor = 'pink'; 
        })
  • 点击每个 li 都会弹出对话框,以前需要给每个 li 注册事件,是非常辛苦的,而且访问 DOM 的次数越多,这会延长整个页面的交互就绪时间。
  • 给ul设置了监听事件,点击子节点li时,li的点击向上层冒泡到了ul,而ul设置有事件监听,就能执行事件监听函数里的代码
  • 事件委托作用: 我们只操作了一次DOM,提高了程序性能

6.常见鼠标事件

鼠标事件触发条件
onclick鼠标点击左键触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onfocus获得鼠标焦点触发
onblur失去鼠标焦点触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发
oncontextmenu右键菜单触发
onselectstart选中文字触发
  • 以上事件使用方法监听事件不需要加on前缀

示例:

<body>
    这段文字不想用于分享
<body>

(1) 右键菜单

contextmenu

		document.addEventListener('contextmenu', function (e) {

            e.preventDefault(); // 阻止默认行为
        })
  • contextmenu:右键菜单,我们可以使用阻止默认行为来禁用右键菜单

(2)选中文字

selectstart

 	document.addEventListener('selectstart', function (e) {
            e.preventDefault(); // 阻止默认行为
        })
  • selectstart:选中文字,我们可以使用阻止默认行为来禁止选中文字

7.鼠标事件对象

​ 鼠标事件对象: MouseEvent

鼠标事件对象属性说明
e.clientX返回鼠标在可视区的坐标x
e.clientY返回鼠标在可视区的坐标y
e.pageX返回鼠标在页面的坐标x
e.pageY返回鼠标在页面的坐标要y
e.screenX返回鼠标在屏幕的坐标x
e.screenY返回鼠标在屏幕的坐标y

示例:

 	<style>
        body {
            height: 3000px;
        }
    </style>

鼠标事件对象的坐标属性

client page screen

		document.addEventListener('click', function (e) {
            // console.log(e);
            // 1.client
            console.log(e.clientX);
            console.log(e.clientY);
           
            // 2. page  
            console.log(e.pageX);
            console.log(e.pageY);
     
            // 3.screen 
            console.log(e.screenX);
            console.log(e.screenY);
        })
  • client: 鼠标在可视区的坐标(x,y)
  • page: 鼠标在页面的坐标(x,y)
  • screen: 鼠标在屏幕的坐标(x,y)

8.常见的键盘事件

键盘事件触发条件
keyup某个键盘弹起触发
keydown某个键盘按下触发
keypress某个键盘按下触发(但不识别功能键 如ctrl,shift,方向键等)

示例:

		// 1.keyup
        document.addEventListener('keyup', function () {

            console.log('我弹起了!');
        })

        // 2.keydown
        document.addEventListener('keydown', function () {

            console.log('我按下了down');
        })
        // 3.keypress               
        document.addEventListener('keypress', function () {

            console.log('我按下了press');
        })
  • 三者都触发时的顺序: keydown->keypress->keyup

9.键盘事件对象

​ 键盘事件对象: KeyboardEvent

键盘事件对象属性说明
keyCode返回该键的ASCII值

键盘事件对象中的属性

keyCode

 		// keyup和keydown事件不能区分字的大小写 如a何A都是65
        document.addEventListener('keyup', function (e) {

            // e.keyCode
            console.log('up:' + e.keyCode);

            // 
            if (e.keyCode === 65) {
                alert('您按下了A键');
            } else {
                alert('您没按下A键');
            }
        })

        // 
        document.addEventListener('keypress', function (e) {

            console.log('press:' + e.keyCode);
        })

  • 我们可以利用keyCode返回的ASICC值来判断用户按下了哪个键

  • keyup和keydown事件不能区分字的大小写 如: a何A都是65,keypress能区分键盘字母的大小写。

二.BOM

1.BOM简介

BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window

​ BOM由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。

​ BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分。

  • window对象是浏览器的顶级对象,它具有双重角色。
  • 它是JS访问浏览器窗口的一个接口。
  • 它是一个全局对象。定义在全局作用域中的变量、函数都会变成window的属性和方法,调用的时候是可以忽略window的,如alert(),prompt()都属于window的方法

window下面的对象: document , location, navigation ,screen,history

2.window对象的常见事件

​ windows对象的常见事件: 1.页面加载事件2.调整窗口大小事件

  • 页面加载事件: loadDOMContentLoaded
  • 调整窗口大小事件:resize

1.页面加载事件

​ 有了window对象的页面加载事件,我们的js代码在哪个位置都能执行,它是等页面加载后才执行。

load

		// 传统方式
        window.onload = function () {

             var btns = document.querySelector('button');
             btns.onclick = function () {
                 alert(66);
             }
         }
         window.onload = function () {
             var btns = document.querySelector('button');
             alert(77);
         } 
        // 监听事件方式
        window.addEventListener('load', function () {

            var btns = document.querySelector('button');
            btns.addEventListener('click', function () {
                alert(88);
            })

        })
  • load: 等页面内容全部加载后,执行load事件。

DOMContentLoaded

		window.addEventListener('DOMContentLoaded', function () {
            alert(11);
        })

  • DOMContentLoaded: 等DOM加载完毕,就执行DOMContentLoaded事件(ie9以上支持)

什么时候用DOMContentLoaded?

​ 如果页面的图片很多的话,从用户访问到load触发可能需要较长的时间,交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded事件比较合适。

load和DOMContentLoaded的区别:

  • DOMContentLoaded只是等DOM加载完毕就执行,不包含图片,flash,css等就可以执行,加载速度要比load快

2.调整窗口大小事件

resize

示例:

		<style>
        	div {
            width: 200px;
            height: 200px;
            background-color: pink;
       	 	}
    	</style>
		<div></div>
		window.addEventListener('load', function () {
            var btns = document.querySelector('div');
            window.addEventListener('resize', function () {

                // innerWidth能获取当前屏幕宽度
                console.log(window.innerWidth);
                console.log('窗口在大小变化');
                if (innerWidth < 800) {
                    btns.style.display = 'none';
                } else {
                    btns.style.display = 'block';
                }
            })
        })
  • innerWidth能获取当前屏幕宽度
  • 当窗口大小发生变化时,resize事件就会触发
  • 我们可以利用resize做响应式效果,如以上例子屏幕宽度<800,则盒子隐藏

3.定时器

​ 定时器有: 1. setTimeout() 2. setInterval()

(1)setTimeout(调用函数, [延迟的毫秒数])

		// 写法方式1:匿名函数
          setTimeout(function () {
 
             console.log('BOMM!');
         }, 3000);   // 3秒 

        // 写法方式2:自定义函数
        function callback() {
            console.log('BOMM!');
        }
        var timer = setTimeout(callback, 3000);
        // setTimeout('callback()', 3000);     // 调用方式2(了解  不提倡这种写法)


  • setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数
  • setTimeout()方法的第一个参数是回调函数,第二个参数是延迟的毫秒数

清除setTimeout()定时器: clearTimeOut(timeoutID)

示例:

<button>停止定时器按钮</button>
// 清除定时器
        //         
        var timer = setTimeout(function () {
            console.log('BOOM!爆炸')
        }, 5000);

        var btns = document.querySelector('button');
        btns.addEventListener('click', function () {

            clearTimeout(timer);       
        })
  • clearTimeout() 可以清除setTimeout定时器,参数是定时器的名称

  • 开发中,网页经常会有很多不同的定时器,所以我们经常给定时器加上标识(名字)

  • 以上例子当点击button时,就可以清除定时器timer

(2) setInterval(回调函数,延迟时间)

 		setInterval(function () {

            console.log('继续输出!');
        }, 1000);
  • setInterval()用法全都和setTimeout()一样

清除setInterval()定时器: clearInterval(timeoutID)

示例:


    <button class="begin">开始定时器</button>
    <button class="stop">结束定时器</button>
		var begin = document.querySelector('.begin');
        var stop = document.querySelector('.stop');
        var timer = null;   // timer  全局变量(这样其他的函数就能访问到它了)  null是一个空对象

        begin.addEventListener('click', function () {
            // 1.开启定时器
            timer = setInterval(function () {
                console.log('how are you?')
            }, 1000)
        })

        stop.addEventListener('click', function () {
            // 2.结束定时器
            clearInterval(timer);
        })
  • clearInterval()可以清除setInterval()定时器

setInterval()和setTimeout()的区别: setInterval()是每隔多少时间然后去执行回调函数,可以重复执行很多次。setTimeout()是只能执行一次

4.JS执行机制

1.JS单线程

​ JavaScript最大的特点就是单线程,也就是说,同一个时间下,只能做一件事。这是因为JavaScript这门脚本语言诞生的使命所致。

​ 单线程所有任务都需要排队,前一个任务结束,才会执行后一个任务。这样会使JS执行的时间过长,这样就会造成页面的渲染效果不连贯,导致页面渲染加载阻塞的感觉。

2.JS同步和异步

​ 为了解决单线程存在的问题, 利用多核cpu的计算能力, HTML5提出Web Worker标准, 允许JavaScript脚本创建多个线程, 于是就有了同步和异步。

  • 同步: 前一个任务执行结束后再执行下一个任务(排队的形式),程序的执行顺序与任务的排列顺序是一致的、同步的。

  • 异步: 执行一个任务的同时另一个任务也可以执行。

3.JS同步异步执行过程

​ JS中把所有任务分为了: 1.同步任务 2.异步任务

  • 同步任务: 同步任务都在主线程上执行,形成一个执行栈。

  • 异步任务: 异步任务都是通过回调函数了来实现的。异步任务相关的回调函数会添加到任务队列(消息队列)中。

  • 异步任务一般有三种: 1.普通事件,如: click,resize 2.资源加载,如: load,error等 3.定时器,如: setTimeout,setInterval。

执行过程:

1.先执行执行栈中的同步任务

2.异步任务(回调函数)放入消息队列中

3.一旦执行栈中的所有同步任务执行完毕,系统将按次序读取消息队列中的异步任务,被读取的异步任务结束等待状态,进入执行栈中,开始执行。

5.location对象

​ window给我们提供了一个location属性用于获取或设置页面的url,并且可以解析url。这个属性返回的是一个对象,所以我们也称这个属性为location对象。

1.URL

统一资源定位符(Uniform Resource Locator,URL)是互联网上标准资源的地址。 互联网上的每个文件都有一个唯一的URL,它包含信息指出文件的位置以及浏览器应该怎么去处理它。

//URL一般语法格式
protocol://host[:port]/path/[?query]#fragment
  • protocol: 通信协议,常用的http,ftp,maito
  • host:主机名(域名) www.xxx.com
  • port: 端口号(可选参数),省略时使用的是默认端口,如http默认端口为80
  • path:路径,由0个或者多个’/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
  • query: 参数 以键值对的形式 '&'符号分隔开
  • fragment: 片段 #后面内容 常见于链接(锚点)

2.location对象的属性

location对象属性返回值
location.href获取或设置整个url
location.host返回主机(域名): www.xxx.com
location.port返回端口号
location.pathname返回路径
location.search返回参数( ?后面的内容)
location.hash返回片段(#后面的内容 常见于锚点链接)

location对象属性使用,如:

获取url地址

location.url

设置url地址

location.url = 'http://www.xxx.com'

3.location对象方法

location对象方法返回值
location.assign()跟href一样,可以跳转页面(重定向页面) 能记录历史 回退页面
location.replace()替换当前页面,不记录历史,不能回退页面
location.reload()重新加载页面,相当于刷新(f5) 参数为true(强制刷新) ctrl+f5

location对象方法使用,如:

重定向页面

location.assign('http://www.xxx.com');

6.navigator对象

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent

​ userAgent属性可以返回客户端发送服务端的user-agent头部的值。通过user-agent头部的值,我们可以判断用户是以哪个终端打开页面,然后实现相应的跳转方式。

示例:

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
            window.location.href = "./m.jd";      // 手机
        } else {
            window.location.href = "./www.jd.com";      //电脑
        }
  • if(navigator.userAgent.match(/(移动端类型))) {}

7.history对象

​ window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的url。

history对象方法作用
back()后退功能
forword()前进功能
go(参数)前进后退功能,参数如果是1,则前进一个页面,-1,则后退一个页面

history对象方法使用,如:

后退一页

history.go(-1);         
         |

| ----------------- | ------------------------------------ |
| location.href | 获取或设置整个url |
| location.host | 返回主机(域名): www.xxx.com |
| location.port | 返回端口号 |
| location.pathname | 返回路径 |
| location.search | 返回参数( ?后面的内容) |
| location.hash | 返回片段(#后面的内容 常见于锚点链接) |

location对象属性使用,如:

获取url地址

location.url

设置url地址

location.url = 'http://www.xxx.com'

3.location对象方法

location对象方法返回值
location.assign()跟href一样,可以跳转页面(重定向页面) 能记录历史 回退页面
location.replace()替换当前页面,不记录历史,不能回退页面
location.reload()重新加载页面,相当于刷新(f5) 参数为true(强制刷新) ctrl+f5

location对象方法使用,如:

重定向页面

location.assign('http://www.xxx.com');

6.navigator对象

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent

​ userAgent属性可以返回客户端发送服务端的user-agent头部的值。通过user-agent头部的值,我们可以判断用户是以哪个终端打开页面,然后实现相应的跳转方式。

示例:

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
            window.location.href = "./m.jd";      // 手机
        } else {
            window.location.href = "./www.jd.com";      //电脑
        }
  • if(navigator.userAgent.match(/(移动端类型))) {}

7.history对象

​ window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的url。

history对象方法作用
back()后退功能
forword()前进功能
go(参数)前进后退功能,参数如果是1,则前进一个页面,-1,则后退一个页面

history对象方法使用,如:

后退一页

history.go(-1);         
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值