DOM概述

在这里插入图片描述

DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个JavaScript 对象,从而可以用脚本进行各种操作(比如对元素增删内容)

浏览器会根据 DOM 模型,将结构化文档HTML解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口

DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是 JavaScript 语法的一部分,但是 DOM 操作是 JavaScript最常见的任务,离开了 DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM 操作的语言

节点
DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子
在这里插入图片描述
节点的类型有七种

Document:整个文档树的顶层节点
DocumentType:doctype标签
Element:网页的各种HTML标签
Attribute:网页元素的属性(比如class=“right”)
Text:标签之间或标签包含的文本
Comment:注释
DocumentFragment:文档的片段

节点树
一个文档的所有节点,按照所在的层级,可以抽象成一种树状结构。这种树状结构就是 DOM 树。它有一个顶层节点,下一层都是顶层节点的子节点,然后子节点又有自己的子节点,就这样层层衍生出一个金字塔结构,倒过来就像一棵树

浏览器原生提供document节点,代表整个文档

document
// 整个文档树

除了根节点,其他节点都有三种层级关系

父节点关系(parentNode):直接的那个上级节点
子节点关系(childNodes):直接的下级节点
同级节点关系(sibling):拥有同一个父节点的节点

Node.nodeType属性
不同节点的nodeType属性值和对应的常量如下

文档节点(document):9,对应常量
Node.DOCUMENT_NODE
元素节点(element):1,对应常量Node.ELEMENT_NODE
属性节点(attr):2,对应常量Node.ATTRIBUTE_NODE
文本节点(text):3,对应常量Node.TEXT_NODE
文档片断节点(DocumentFragment):11,对应常量
Node.DOCUMENT_FRAGMENT_NODE

document.nodeType // 9
document.nodeType === Node.DOCUMENT_NODE //true

document对象_属性

在这里插入图片描述
document对象是文档的根节点,每张网页都有自己的document对象只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用

document.doctype
document.doctype,指向 <DOCTYPE> 节点,即文档类型(Document Type Declaration,简写DTD)节点。HTML 的文档类型节点,一般写成 <!DOCTYPE html> 。如果网页没有声明 DTD,该属性返回null

var doctype = document.doctype;
doctype // "<!DOCTYPE html>"

document.documentElement
document.documentElement属性返回当前文档的根节点(root),一般是 <html> 节点

document.documentElement

document.body,document.head
document.body属性指向 <body> 节点,document.head属性指向<head> 节点

document.body;
document.head;

document.forms
document.forms 属性返回所有 <form> 表单节点

var selectForms = document.forms;

document.images
document.images 属性返回页面所有 <img> 图片节点

var imglist = document.images;
for(var i = 0; i < imglist.length; i++) {
  if (imglist[i].src === 'banner.png') {
    console.log("页面存在banner");
 }else{
	console.log("页面不存在banner");
 }
}

document.scripts
document.scripts 属性返回所有 <script> 节点

var scripts = document.scripts;
if (scripts.length !== 0 ) {
  console.log('当前网页有脚本');
}

document.domain
document.domain 属性返回当前文档的域名

document.domain;  // www.itbaizhan.com

document对象_方法/获取元素

在这里插入图片描述
document.getElementsByTagName()
document.getElementsByTagName 方法搜索 HTML 标签名,返回符合条件的元素。它的返回值是一个类似数组对象( HTMLCollection 实例),可以实时反映 HTML 文档的变化。如果没有任何匹配的元素,就返回一个空集

var paras = document.getElementsByTagName('p');

如果传入 * ,就可以返回文档中所有 HTML 元素

var allElements = document.getElementsByTagName('*');

document.getElementsByClassName()
document.getElementsByClassName 方法返回一个类似数组的对象( HTMLCollection 实例),包括了所有 class 名字符合指定条件的元素,元素的变化实时反映在返回结果中

var elements = document.getElementsByClassName(names);

由于 class 是保留字,所以 JavaScript 一律使用 className 表示 CSS 的class 参数可以是多个 class ,它们之间使用空格分隔

var elements = document.getElementsByClassName('foo bar');

document.getElementsByName()
document.getElementsByName 方法用于选择拥有 name 属性的 HTML 元素(比如 <form><radio><img> 等),返回一个类似数组的的对象( NodeList 实例),因为 name 属性相同的元素可能不止一个

// 表单为 <form name="itbaizhan"></form>
var forms = document.getElementsByName('itbaizhan');

document.getElementById()
document.getElementById 方法返回匹配指定 id 属性的元素节点。如果没有发现匹配的节点,则返回 null

var elem = document.getElementById('para1');

注意,该方法的参数是大小写敏感的。比如,如果某个节点的 id 属性是 main ,那么document.getElementById('Main') 将返回 null

document.querySelector()

document.querySelector 方法接受一个 CSS 选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回 null

var el1 = document.querySelector('.myclass');

document.querySelectorAll()
document.querySelectorAll 方法与 querySelector 用法类似,区别是返回一个NodeList 对象,包含所有匹配给定选择器的节点

var elementList = document.querySelectorAll('.myclass');

document对象_方法/创建元素

在这里插入图片描述
document.createElement()
document.createElement 方法用来生成元素节点,并返回该节点

var newDiv = document.createElement('div');

document.createTextNode()
document.createTextNode 方法用来生成文本节点( Text 实例),并返回该节点。它的参数是文本节点的内容

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

document.createAttribute()
document.createAttribute 方法生成一个新的属性节点( Attr 实例),并返回它

var attribute = document.createAttribute(name);
var root = document.getElementById('root');
var it = document.createAttribute('itbaizhan');
it.value = 'it';
root.setAttributeNode(it);

Element对象_属性

在这里插入图片描述
Element对象对应网页的 HTML 元素。每一个 HTML 元素,在DOM 树上都会转化成一个Element节点对象(以下简称元素节点)

Element.id
Element.id 属性返回指定元素的 id 属性,该属性可读写

// HTML 代码为 <p id="foo">
var p = document.querySelector('p');
p.id // "foo"

Element.className
className 属性用来读写当前元素节点的 class 属性。它的值是一个字符串,每个 class 之间用空格分割

// HTML 代码 <div class="one two three"
id ="myDiv"></div>
var div = document.getElementById('myDiv');
div.className

Element.classList
classList 对象有下列方法

add() :增加一个 class。
remove() :移除一个 class。
contains() :检查当前元素是否包含某个 class。
toggle() :将某个 class 移入或移出当前元素。

var div = document.getElementById('myDiv');
div.classList.add('myCssClass');
div.classList.add('foo', 'bar');
div.classList.remove('myCssClass');
div.classList.toggle('myCssClass'); // 如果myCssClass 不存在就加入,否则移除
div.classList.contains('myCssClass'); // 返回true 或者 false

Element.innerHTML
Element.innerHTML 属性返回一个字符串,等同于该元素包含的所有HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括 <HTML><body> 元素

el.innerHTML = '';

Element.innerText
innerTextinnerHTML 类似,不同的是 innerText 无法识别元素,会直接渲染成字符串

Element获取元素位置一

在这里插入图片描述
Element.clientHeight,Element.clientWidth
Element.clientHeight 属性返回一个整数值,表示元素节点的 CSS 高度(单位像素),只对块级元素生效,对于行内元素返回 0 。如果块级元素没有设置 CSS 高度,则返回实际高度

除了元素本身的高度,它还包括 padding 部分,但是不包括 bordermargin 。如果有水平滚动条,还要减去水平滚动条的高度。注意,这个值始终是整数,如果是小数会被四舍五入。

Element.clientWidth 属性返回元素节点的 CSS 宽度,同样只对块级元素有效,也是只包括元素本身的宽度和 padding ,如果有垂直滚动条,还要减去垂直滚动条的宽度。

document.documentElementclientHeight 属性,返回当前视口的高度(即浏览器窗口的高度)。 document.body 的高度则是网页的实际高度。

// 视口高度
document.documentElement.clientHeight
// 网页总高度
document.body.clientHeight

Element.clientLeft,Element.clientTop
Element.clientLeft 属性等于元素节点左边框(left border)的宽度(单位像素),不包括左侧的 paddingmargin 。如果没有设置左边框,或者
是行内元素( display: inline ),该属性返回 0 。该属性总是返回整数值,如果是小数,会四舍五入

Element.clientTop 属性等于网页元素顶部边框的高度(单位像素)

var box = document.getElementById("box");
console.log(box.clientLeft);
console.log(box.clientTop);

Element.scrollHeight,Element.scrollWidth
Element.scrollHeight 属性返回一个整数值(小数会四舍五入),表示当前元素的总高度(单位像素),它包括 padding ,但是不包括 border
margin 以及水平滚动条的高度(如果有水平滚动条的话)

Element.scrollWidth 属性表示当前元素的总宽度(单位像素),其他地方都与 scrollHeight 属性类似。这两个属性只读

整张网页的总高度可以从document.documentElementdocument.body 上读取

// 返回网页的总高度
document.documentElement.scrollHeight
document.body.scrollHeight

Element获取元素位置二

Element.scrollLeft,Element.scrollTop
Element.scrollLeft 属性表示当前元素的水平滚动条向右侧滚动的像素数量, Element.scrollTop 属性表示当前元素的垂直滚动条向下滚动的像素数量。对于那些没有滚动条的网页元素,这两个属性总是等于0

如果要查看整张网页的水平的和垂直的滚动距离,要从document.documentElement 元素上读取

document.documentElement.scrollLeft
document.documentElement.scrollTop

Element.offsetHeight,Element.offsetWidth
Element.offsetHeight 属性返回一个整数,表示元素的 CSS 垂直高度(单位像素),包括元素本身的高度、paddingborder,以及水平滚动条的高度(如果存在滚动条)。

Element.offsetWidth 属性表示元素的 CSS 水平宽度(单位像素),其他都与 Element.offsetHeight 一致。

这两个属性都是只读属性,只比Element.clientHeightElement.clientWidth 多了
边框的高度或宽度。如果元素的 CSS 设为不可见(比如 display:none; ),则返回 0

Element.offsetLeft,Element.offsetTop
Element.offsetLeft 返回当前元素左上角相对于 Element.offsetParent 节点的水平位移, Element.offsetTop 返回垂直位移,单位为像素。通常,这两个值是指相对于父节点的位移

<div class="parent">
    <div class="box" id="box"></div>
</div>
.parent{
    width: 200px;
    height: 200px;
    background: red;
    position: relative;
    left: 50px;
    top: 50px;
}
.box{
    width: 100px;
    height: 100px;
    background: yellow;
    position: relative;
    left: 50px;
    top: 50px;
}
var box = document.getElementById("box");
console.log(box.offsetLeft);
console.log(box.offsetTop);

Element对象_方法

在这里插入图片描述
Element.focus()
Element.focus 方法用于将当前页面的焦点,转移到指定元素上

document.getElementById('my-span').focus();

Element.blur()
Element.blur 方法用于将焦点从当前元素移除

Element.remove()
Element.remove 方法用于将当前元素节点从它的父节点移除

var el = document.getElementById('mydiv');
el.remove();

Element.getBoundingClientRect()
Element.getBoundingClientRect 方法返回一个对象,提供当前元素节点的大小、位置等信息,基本上就是 CSS 盒状模型的所有信息

var rect = obj.getBoundingClientRect();

getBoundingClientRect 方法返回的 rect 对象,具有以下属性(全部为只读)

x :元素左上角相对于视口的横坐标
y :元素左上角相对于视口的纵坐标
height :元素高度
width :元素宽度
left :元素左上角相对于视口的横坐标,与 x 属性相等
right :元素右边界相对于视口的横坐标(等于 x + width )
top :元素顶部相对于视口的纵坐标,与 y 属性相等
bottom :元素底部相对于视口的纵坐标(等于 y + height )

Attribute属性的操作

在这里插入图片描述
HTML 元素包括标签名和若干个键值对,这个键值对就称为“属性”(attribute)
元素节点提供四个方法,用来操作属性

getAttribute()
setAttribute()
hasAttribute()
removeAttribute()

Element.getAttribute()
Element.getAttribute 方法返回当前元素节点的指定属性。如果指定属性不存在,则返回 null

// HTML代码为
// <div id="div1" align="left">
var div = document.getElementById('div1');
div.getAttribute('align') // "left"

Element.setAttribute()
Element.setAttribute 方法用于为当前元素节点新增属性。如果同名属性已存在,则相当于编辑已存在的属性

var d = document.getElementById('d1');
d.setAttribute('align', 'center');

下面是对 img 元素的 src 属性赋值的例子

var myImage = document.querySelector('img');
myImage.setAttribute('src','images/girl.png');

Element.hasAttribute()
Element.hasAttribute 方法返回一个布尔值,表示当前元素节点是否包含指定属性

var d = document.getElementById('box');
if (d.hasAttribute('align')) {
  d.setAttribute('align', 'center');
}

Element.removeAttribute()
Element.removeAttribute 方法用于从当前元素节点移除属性

// HTML 代码为
// <div id="box" align="left" width="200px">
document.getElementById('box').removeAttribute('align');
// 现在的HTML代码为
// <div id="box" width="200px">

dataset 属性
有时,需要在HTML元素上附加数据,供 JavaScript 脚本使用。一种解决方法是自定义属性
使用标准提供的 data-* 属性

<div id="box" data-itbaizhan="itbaizhan">

然后,使用元素节点对象的 dataset 属性,它指向一个对象,可以用来操作 HTML 元素标签的 data-* 属性

var n = document.getElementById('box');
n.dataset.itbaizhan // itbaizhan
n.dataset.itbaizhan = 'itbaizhan'

Text 节点

在这里插入图片描述
文本节点( Text )代表元素节点( Element )和属性节点( Attribute )的文本内容。

Text节点属性

data
data 属性用来设置或读取文本节点的内容

// 读取文本内容
document.querySelector('p').firstChild.data
// 设置文本内容
document.querySelector('p').firstChild.data = 'Hello World';

length
length 属性返回当前文本节点的文本长度

(new Text('Hello')).length // 5

Text节点方法

appendData()
Text 节点尾部追加字符串

// <p>Hello World</p>
var pElementText = document.querySelector('p');
pElementText.firstChild.appendData('!');// 页面显示 Hello World!

deleteData()
删除 Text 节点内部的子字符串,第一个参数为子字符串开始位置,第二个参数为子字符串长度

// <p>Hello World</p>
var pElementText = document.querySelector('p');
pElementText.firstChild.deleteData(7, 5);
// 页面显示 Hello W

insertData()
Text 节点插入字符串,第一个参数为插入位置,第二个参数为插入的子字符串

// <p>Hello World</p>
var pElementText = document.querySelector('p');
pElementText.firstChild.insertData(7, 'Hello');
// 页面显示 Hello WHello

replaceData()
用于替换文本,第一个参数为替换开始位置,第二个参数为需要被替换掉的长度,第三个参数为新加入的字符串

// <p>Hello World</p>
var pElementText = document.querySelector('p');
pElementText.firstChild.replaceData(7, 5,'World');
// 页面显示 Hello WWorld

substringData()
用于获取子字符串,第一个参数为子字符串在 Text 节点中的开始位置,第二个参数为子字符串长度

// <p>Hello World</p>
var pElementText = document.querySelector('p');
pElementText.firstChild.substringData(7, 10);
// 页面显示不变,返回"World "

remove()
remove 方法用于移除当前 Text 节点

// <p>Hello World</p>
document.querySelector('p').firstChild.remove()
// 现在 HTML 代码为
// <p></p>

DocumentFragment 节点

在这里插入图片描述
DocumentFragment 节点代表一个文档的片段,它一般用于构建一个DOM 结构,然后插入当前文档

var docFrag = document.createDocumentFragment();
var li = document.createElement('li');
li.innerHTML = 'Hello World';
docFrag.appendChild(li);
document.querySelector('ul').appendChild(docFrag);

温馨提示
DocumentFragment 节点本身不能被插入当前文档,插入文档中的是他里面的子元素
应用场景
多次操作DOM,可以使用 DocumentFragment 变成一次操作,节省了内存的消耗

Node 节点属性_nodeName

在这里插入图片描述
所有 DOM 节点都继承了 Node 接口,拥有一些共同的属性和方法。这是 DOM 操作的基础

节点的类型有七种

Document:整个文档树的顶层节点
DocumentType:doctype标签
Element:网页的各种HTML标签
Attribute:网页元素的属性(比如class=“right”)
Text:标签之间或标签包含的文本
Comment:注释
DocumentFragment:文档的片段

nodeName 属性返回节点的名称

// <div id="box">hello world</div>
var box = document.getElementById('box');
var docFrag = document.createDocumentFragment();
console.log(box.nodeName) // "DIV"
console.log(document.nodeName);
console.log(box.getAttributeNode("id").nodeName);
console.log(box.firstChild.nodeName);
console.log(docFrag.nodeName);

不同节点的 nodeName 属性值如下

文档节点(document): #document
元素节点(element):大写的标签名
属性节点(attr):属性的名称
文本节点(text): #text
文档片断节点(DocumentFragment): #document-fragment
文档类型节点(DocumentType):文档的类型
注释节点(Comment): #comment

Node 节点属性_nodeValue
nodeValue 属性返回一个字符串,表示当前节点本身的文本值,该属性可读写

// <div id="box">hello world</div>
var box = document.getElementById('box');
box.nodeValue // null
box.firstChild.nodeValue // "hello world"

Node 节点属性_textContent
textContent 属性返回当前节点和它的所有后代节点的文本内容

// <div id="box">This is <span>some</span>
text</div>
document.getElementById('box').textContent
// This is some text

Node 节点属性_nextSibling
Node.nextSibling 属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回 null

// <div id="box1">hello</div><div
id="box2">world</div>
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
box1.nextSibling === box2 // true

nextSibling 属性可以用来遍历所有子节点

var box = document.getElementById('box').firstChild;
while (box !== null) {
  console.log(box.nodeName);
  box = box.nextSibling;
}

Node 节点属性_previousSibling
previousSibling 属性返回当前节点前面的,距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回 null

// <div id="box1">hello</div><div
id="box2">world</div>
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
box2.previousSibling === box1 // true

Node 节点属性_parentNode
parentNode 属性返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)和文档片段节(documentfragment)

if (node.parentNode) {
  node.parentNode.removeChild(node);
}

Node 节点属性_firstChild/lastChild
firstChild 属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回 null

// <p id="p1"><span>First span</span></p>
var p1 = document.getElementById('p1');
p1.firstChild.nodeName // "SPAN"

lastChild 属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回 null 。用法与 firstChild 属性相同

Node 节点属性_childNodes
childNodes 属性返回一个类似数组的对象( NodeList 集合),成员包括当前节点的所有子节点

var children = document.querySelector('ul').childNodes;

使用该属性,可以遍历某个节点的所有子节点

var box = document.getElementById('box');
var children = div.childNodes;
for (var i = 0; i < children.length; i++) {
  // ...
}

Node 节点方法_appendChild()
在这里插入图片描述
appendChild 方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。该方法的返回值就是插入文档的子节点

var p = document.createElement('p');
document.body.appendChild(p);

Node 节点方法_hasChildNodes()
hasChildNodes 方法返回一个布尔值,表示当前节点是否有子节点

var foo = document.getElementById('foo');
if (foo.hasChildNodes()) {
  foo.removeChild(foo.childNodes[0]);
}

Node 节点方法_cloneNode()
cloneNode 方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点。它的返回值是一个克隆出来的新节点

var cloneUL = document.getElementById('list').cloneNode(tru
e);

Node 节点方法_insertBefore()
insertBefore 方法用于将某个节点插入父节点内部的指定位置insertBefore 方法接受两个参数,第一个参数是所要插入的节点newNode ,第二个参数是父节点 parentNode 内部的一个子节点
referenceNodenewNode 将插在 referenceNode 这个子节点的前面。返回值是插入的新节点 newNode

var insertedNode = parentNode.insertBefore(newNode,referenceNode);

Node 节点方法_removeChild()
removeChild 方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点

var box = document.getElementById('box');
box.parentNode.removeChild(box);

温馨提示
这个方法是在 box 的父节点上调用的,不是在 box 上调用的。

Node 节点方法_replaceChild()
replaceChild 方法用于将一个新的节点,替换当前节点的某一个子节点replaceChild 方法接受两个参数,第一个参数 newChild 是用来替换的新节点,第二个参数 oldChild 是将要替换走的子节点。返回值是替换走的那个节点 oldChild

var replacedNode = parentNode.replaceChild(newChild, oldChild);

CSS操作

在这里插入图片描述
HTML 元素的 style 属性
操作 CSS 样式最简单的方法,就是使用网页元素节点的 setAttribute 方法直接操作网页元素的 style 属性

div.setAttribute(
  'style',
  'background-color:red;' + 'border:1px solidblack;'
);

元素节点的 style 属性

var divStyle = document.querySelector('div').style;
divStyle.backgroundColor = 'red';
divStyle.border = '1px solid black';
divStyle.width = '100px';
divStyle.height = '100px';
divStyle.fontSize = '10em';

cssText 属性

var divStyle = document.querySelector('div').style;
divStyle.cssText = 'background-color: red;'
  + 'border: 1px solid black;'
  + 'height: 100px;'
  + 'width: 100px;';

事件处理程序

事件处理程序分为:

  • HTML事件处理
  • DOM0级事件处理
  • DOM2级事件处理
  • IE事件处理

HTML事件

<!DOCTYPE html>
<html>
	<head lang="en">
        <meta charset="UTF-8">
        <title>Js事件详解--事件处理</title>
    </head>
    <body>
        <div id="div">
            <button id="btn1" onclick="demo()">按钮</button>
        </div>
        <script>
            function demo(){
                alert("hello html事件处理");
           }
        </script>
    </body>
</html>

DOM0级事件处理

<body>
    <div id="div">
        <button id="btn1">按钮</button>
    </div>
    <script>
        var btn1=document.getElementById("btn1");
        btn1.onclick=function(){alert("HelloDOM0级事件处理程序1");}//被覆盖掉
        btn1.onclick=function(){alert("HelloDOM0级事件处理程序2");}
    </script>
</body>

DOM2级事件处理

<body>
    <div id="div">
        <button id="btn1">按钮</button>
    </div>
    <script>
        var btn1=document.getElementById("btn1");
      
		btn1.addEventListener("click",demo1);
		      
		btn1.addEventListener("click",demo2);
		      
		btn1.addEventListener("click",demo3);
        function demo1(){
            alert("DOM2级事件处理程序1")
       }
        function demo2(){
            alert("DOM2级事件处理程序2")
       }
        function demo3(){
            alert("DOM2级事件处理程序3")
       }
      
	btn1.removeEventListener("click",demo2);
    </script>
</body>

IE事件处理程序
IE实现了与DOM中类似的两个方法: attachEvent()detachEvent()

事件类型之鼠标事件

常见事件类型

1 鼠标事件
2 键盘事件
3 表单事件
4 窗口事件
5 焦点/剪贴板事件
6 网页状态事件
7 Touch事件

鼠标事件
鼠标事件指与鼠标相关的事件,具体的事件主要有以下一些

1 click:按下鼠标时触发
2 dblclick:在同一个元素上双击鼠标时触发
3 mousedown:按下鼠标键时触发
4 mouseup:释放按下的鼠标键时触发
5 mousemove:当鼠标在节点内部移动时触发。当鼠标持续移动时,该事件会连触发。
6 mouseenter:鼠标进入一个节点时触发,进入子节点不会触发这个事件
7 mouseleave:鼠标离开一个节点时触发,离开父节点不会触发这个事件
8 mouseover:鼠标进入一个节点时触发,进入子节点会再一次触发这个事件
9 mouseout:鼠标离开一个节点时触发,离开父节点也会触发这个事件
10 wheel:滚动鼠标的滚轮时触发

var btn1 = document.getElementById("btn1");
btn1.onclick = function(){
    console.log("click事件");
}

温馨提示
这些方法在使用的时候,除了DOM2级事件,都需要添加前缀on

事件流

事件流描述的是从页面中接受事件的顺序,但有意思的是,微软(IE)和网景(Netscape)开发团队居然提出了两个截然相反的事件流概念,IE的事件流是事件冒泡流(event bubbling),而Netscape的事件流是事件捕获流(event capturing)

事件冒泡
IE提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body onclick="bodyClick()">
<div onclick="divClick()">
        <button onclick="btn()">
            <p onclick="p()">点击冒泡</p>
        </button>
    </div>
    <script>
        function p(){
            console.log('p标签被点击')
       }
        function btn(){
            console.log("button被点击")
       }
        function divClick(event){
            console.log('div被点击');
       }
        function bodyClick(){
            console.log('body被点击')
       }
    </script>
</body>
</html>

事件捕获
事件捕获流的思想是不太具体的DOM节点应该更早接收到事件,而最具体的节点应该最后接收到事件
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <button>
        <p>点击捕获</p>
    </button>
</div>
<script>
    var oP=document.querySelector('p');
    var oB=document.querySelector('button');
    var oD=document.querySelector('div');
    var oBody=document.querySelector('body');
    oP.addEventListener('click',function(){
        console.log('p标签被点击')
         },true);
    oB.addEventListener('click',function(){
        console.log("button被点击")
   },true);
    oD.addEventListener('click',  function()
	{
        console.log('div被点击')
   },true);
  
	oBody.addEventListener('click',function(){
        console.log('body被点击')
   },true);
</script>
</body>
</html>

Event事件对象

事件发生以后,会产生一个事件对象,作为参数传给监听函数。

Event对象属性

1 Event.currentTarget
2 Event.Target
3 Event.type

Event.currentTarget
Event.currentTarget属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点

btn.onclick = function(e){
   console.log(e.currentTarget);
}

Event.target
Event.target属性返回原始触发事件的那个节点,即事件最初发生的节点。事件传播过程中,不同节点的监听函数内部的Event.targetEvent.currentTarget属性的值是不一样的,前者总是不变的,后者则是指向监听函数所在的那个节点对象

// HTML代码为
// <p id="para">Hello <em>World</em></p>
function hide(e) {
  console.log(this === e.currentTarget);  //总是 true
  console.log(this === e.target);  // 有可能不是 true
  e.target.style.visibility = 'hidden';
}
para.addEventListener('click', hide, false);

Event.type
Event.type属性返回一个字符串,表示事件类型。事件的类型是在生成事件的时候。该属性只读

Event对象方法

1 Event.preventDefault()
2 Event.stopPropagation()

Event.preventDefault
Event.preventDefault方法取消浏览器对当前事件的默认行为。比如点击链接后,浏览器默认会跳转到另一个页面,使用这个方法以后,就不会跳转了

btn.onclick = function(e){
    e.preventDefault(); // 阻止默认事件
    console.log("点击A标签");
}

Event.stopPropagation()
stopPropagation方法阻止事件在 DOM 中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上其他的事件监听函数

btn.onclick = function(e){
    e.stopPropagation(); // 阻止事件冒泡
    console.log("btn");
}

事件类型之键盘事件

键盘事件由用户击打键盘触发,主要有keydown、keypress、keyup三个事件

1 keydown:按下键盘时触发。
2 keypress:按下有值的键时触发,即按下 Ctrl、Alt、Shift、Meta 这样无值的键,这个事件不会触 发。对于有值的键,按下时先触发keydown事件,再触发这个事件。
3 keyup:松开键盘时触发该事件

username.onkeypress = function(e){
    console.log("keypress事件");
}

event对象
keyCode:唯一标识

var username =
document.getElementById("username");
username.onkeydown = function(e){
    if(e.keyCode === 13){
        console.log("回车");
   }
}

事件类型之表单事件

表单事件是在使用表单元素及输入框元素可以监听的一系列事件

1 input事件
2 select事件
3 Change事件
4 reset事件
5 submit事件

input事件
input事件当 <input>、<select>、<textarea> 的值发生变化时触发。对于复选
框( <input type=checkbox> )或单选框( <input type=radio> ),用户改变选项时,也会触发这个事件input事件的一个特点,就是会连续触发,比如用户每按下一次按键,就会触发一次input事件。

var username = document.getElementById("username");
username.oninput = function(e){
    console.log(e.target.value);
}

select事件
select事件当在 <input>、<textarea> 里面选中文本时触发

// HTML 代码如下
// <input id="test" type="text" value="Selectme!" />
var elem = document.getElementById('test');
elem.addEventListener('select', function (e)
{
  console.log(e.type); // "select"
}, false);

Change 事件
Change事件当 <input>、<select>、<textarea> 的值发生变化时触发。它与input事件的最大不同,就是不会连续触发,只有当全部修改完成时才会触发

var email = document.getElementById("email");
email.onchange = function(e){
    console.log(e.target.value);
}

reset 事件,submit 事件
这两个事件发生在表单对象 <form> 上,而不是发生在表单的成员上。
reset事件当表单重置(所有表单成员变回默认值)时触发。

submit事件当表单数据向服务器提交时触发。注意,submit事件的发生对象是 <form> 元素,而不是 <button> 元素,因为提交的是表单,而不是按钮

<form id="myForm" onsubmit="submitHandle">
    <button onclick="resetHandle">重置数据
</button>
    <button>提交</button>
</form>
var myForm = document.getElementById("myForm")
function resetHandle(){
    myForm.reset();
}
function submitHandle(){
    console.log("提交");
}

事件类型之窗口事件

1 scroll 事件
2 resize 事件

scroll 事件在文档或文档元素滚动时触发,主要出现在用户拖动滚动条

window.onscroll = function(e){
    var srcrollHeight = document.documentElement.scrollTop;
    console.log(srcrollHeight);
}

resize 事件在改变浏览器窗口大小时触发

window.onresize = function(){
    console.log("窗口发生变化");
}

焦点/剪贴板事件

焦点事件
焦点事件发生在元素节点和document对象上面,与获得或失去焦点相关。它主要包括以下四个事件

1 focus:元素节点获得焦点后触发,该事件不会冒泡。
2 blur:元素节点失去焦点后触发,该事件不会冒泡。
3 focusin:元素节点将要获得焦点时触发,发生在focus事件之前。该事件会冒泡。
4 focusout:元素节点将要失去焦点时触发,发生在blur事件之前。该事件会冒泡。

var username = document.getElementById("username");
username.onfocus = function(e){
   console.log("获得焦点",e.target.value);
}
username.onblur = function(e){
   console.log("失去焦点",e.target.value);
}

剪贴板事件
以下三个事件属于剪贴板操作的相关事件

1 cut:将选中的内容从文档中移除,加入剪贴板时触发。
2 copy:进行复制动作时触发。
3 paste:剪贴板内容粘贴到文档后触发。

var password = document.getElementById("password");
password.oncut = function(e){
    console.log("剪切");
}
password.oncopy = function(e){
    console.log("复制");
}
var email = document.getElementById("email");
email.onpaste = function(){
    console.log("粘贴");
}

网页状态事件

1 load
2 DOMContentLoaded 事件
3 readystatechange 事件

Load事件
资源加载完成之后触发,包含DOM和图片等资源都加载完成后,才会触发load

var image = new Image();
image.src = "http://iwenwiki.com/banner1.png"
image.onload = function(){
    console.log("图片的资源加载完成了");
    document.body.appendChild(image);
}

DOMContentLoaded 事件
网页下载并解析完成以后,浏览器就会在document对象上触发DOMContentLoaded 事件。这时,仅仅完成了网页的解析(整张页面的 DOM 生成了),所有外部资源(样式表、脚本、iframe 等等)可能还没有下载结束。也就是说,这个事件比load事件,发生时间早的多

document.addEventListener('DOMContentLoaded',
function (event) {
  console.log('DOM生成');
});

readystatechange 事件
此事件我们会放在网络请求部分讲解

Touch事件

在这里插入图片描述
触摸引发的时间,有以下几种。可以通过TouchEvent.type属性,查看到底发生的是哪一种事件

1 touchstart:用户开始触摸时触发,它的target属性返回发生触摸的元素节点
2 touchend:用户不再接触触摸屏时触发
3 touchmove:用户移动触摸点时触发
4 touchcancel:系统取消touch事件的时候触发(使用率低)

var box = document.getElementById("box");
box.addEventListener("touchend",function(){
    console.log("抬起来了");
})
box.addEventListener("touchstart",function(e
){
    console.log("触摸屏幕",e);
})
box.addEventListener("touchmove",function(){
    console.log("移动");
})

温馨提示
上述所有事件,都必须用 DOM2 级事件处理

事件代理(事件委托)

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)

var ul = document.querySelector('ul');
ul.addEventListener('click', function (event)
{
  if (event.target.tagName.toLowerCase() === 'li') {
    // some code
 }
});

this关键字

事件中的this监听函数内部的this指向触发事件的那个元素节点

// HTML 代码如下
// <button id="btn">点击</button>
var btn = document.getElementById('btn');
// 写法一
btn.onclick = function () {
  console.log(this.id);
};
// 写法二
btn.addEventListener('click',function (e) {
    console.log(this.id);
},false);

对象中的this
永远指向调用者,而难得就是你是否可以找到调用者

函数_闭包概念

闭包(closure)是 Javascript 语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现

理解闭包,首先必须理解变量作用域

变量的作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域

变量的作用域无非就是两种

1 全局变量
2 局部变量

var n = 100;
function getNum(){
    console.log(n);
}
getNum(); // 100

另一方面,在函数外部自然无法读取函数内的局部变量

function getNum(){
    var n = 100;
}
console.log(n); // error

温馨提示
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量

如何从外部读取局部变量

处于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是不办不到的,只有通过变通方法才能实现,那就是在函数的内部,再定义一个函数

function getNum(){
    var n = 100;
    function getN(){
        alert(n); // 100
   }
}

既然 getN 可以读取 getNum 中的局部变量,那么只要把 getN 作为返回值,我们不就可以在 getNum 外部读取它的内部变量了吗

function getNum(){
    var n = 100;
    function getN(){
        console.log(n);
   }
    return getN;
}
var result = getNum();
result(); // 100

闭包的概念
上述代码中的 getN 函数就是闭包

各种专业文献上的"闭包"(closure)定义非常抽象,很难看懂。我们参考老前辈的理解是:闭包就是能够读取其他函数内部变量的函数

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

闭包特点

1 读取函数内部的变量
2 变量的值始终保持在内存中

读取函数内部的变量

function getNum(){
    var n = 100;
    function getN(){
        console.log(n);
   }
    return getN;
}
var result = getNum();
result(); // 100

变量的值始终保持在内存中
观察多次调用函数, n 的变化

function getNum(){
    var n = 100;
    n++;
    console.log(n);
}
getNum(); // 101
getNum(); // 101

n 放入到函数中进行增加,然后观察 n 的变化

function getNum() {
    var n = 100;
    nAdd = function () {
        n += 1
   }
    console.log(n);
}
getNum(); // 100
nAdd();
getNum() // 100

增加闭包,在观察 n 的变化

function getNum() {
    var n = 100;
    nAdd = function () {
        n += 1
   }
    function getN() {
        console.log(n);
   }
    return getN;
}
var result = getNum();
result(); // 100
nAdd();
result(); // 101

使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题

闭包应用场景

在这里插入图片描述

创建一个函数,声明一个数组,然后向入组中放入一个函数,函数值为 i * i

function count() {
    var arr = [];
    for (var i = 1; i <= 3; i++) {
        arr.push(function () {
            return i * i;
       });
   }
    return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
console.log(f1(),f2(),f3()); // 16 16 16

原因就在于返回的函数引用了变量 i ,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量 i 已经变成了 4 ,因此最终结果为 16

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续发生变化的变量

如果一定要引用循环变量怎么办? 方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变

function count() {
    var arr = [];
    for (var i = 1; i <= 3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
           }
       })(i));
   }
    return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 1
f2(); // 4
f3(); // 9

闭包中的this关键字

代码片段一

var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        return function(){
            return this.name;
       };
   }
};
alert(object.getNameFunc()());

代码片段二

var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        var that = this;
        return function(){
            return that.name;
       };
   }
};
alert(object.getNameFunc()());

DOM实操_Tab切换(上)

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
       * {
            margin: 0;
            padding: 0;
       }
        body {
            background-color: gray;
       }
        .container {
            width: 300px;
            height: 300px;
            background-color: white;
            margin: 100px auto;
       }
        .up {
            height: 50px;
            width: 100%;
       }
        .up ul {
            list-style: none;
            text-align: center;
       }
        .up ul li {
            width: 60px;
            height: 50px;
            float: left;
            line-height: 50px;
       }
        .up ul li a {
            text-decoration: none;
            font-size: 20px;
       }
        .down {
            height: 250px;
            width: 100%;
            position: relative;
            text-align: center;
       }
        .down div {
            position: absolute;
            line-height: 100px;
            height: 100%;
            width: 100%;
              display: none;
       }
        .select {
            border-bottom: 2px solid orange;
       }
        .down .div_select {
            display: block;
       }
    </style>
</head>
<body>
    <div class="container">
        <div class="up">
            <ul>
                <li class="select"><a href="#">百度</a></li>
                <li><a href="#">新浪</a></li>
                <li><a href="#">淘宝</a></li>
                <li><a href="#">京东</a></li>
                <li><a href="#">网易</a></li>
            </ul>
        </div>
        <div class="down">
            <div class="div_select">百度百度百度</div>
            <div>新浪新浪新浪</div>
            <div>淘宝淘宝淘宝</div>
            <div>京东京东京东</div>
            <div>网易网易网易</div>
        </div>
        </div>
</body>
</html>

DOM实操_Tab切换(下)

var lis = document.querySelector(".up").querySelectorA
ll("li");
var divs = document.querySelector(".down").querySelecto
rAll("div");
for(var i = 0;i<lis.length;i++){
   (function(i){
        lis[i].onmouseenter = function(){
            for(var j = 0;j<lis.length;j++){
              
			lis[j].removeAttribute("class");
			              
			divs[j].removeAttribute("class");
			 }
          
			lis[i].setAttribute("class","select")
			          
		divs[i].setAttribute("class","div-select")
			  }
		}(i))
}

DOM实操-瀑布流-页面布局

瀑布流
瀑布流是一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部

瀑布流特点

1 多列布局
2 每列等宽
3 上拉加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initialscale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./css/style.css">
</head>
<body>
    <div id="container">
        <div class="box">
            <div class="boximg">
                <img src="./img/1.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
            <img src="./img/2.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/3.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/4.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/5.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/6.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/7.jpeg"alt="">
		</div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/8.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/9.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/10.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/11.jpg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/10.jpeg"alt="">
            </div>
        </div>
          <div class="box">
            <div class="boximg">
                <img src="./img/11.jpg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/10.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/11.jpg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/10.jpeg"alt="">
            </div>
        </div>
        <div class="box">
            <div class="boximg">
                <img src="./img/11.jpg"alt="">
            </div>
        </div>
    </div>
    <script src="./js/index.js"></script>
    </body>
</html>
*{
    padding: 0;
    margin: 0;
}
#container{
    position: relative;
}
.box{
    padding: 5px;
    float: left;
}
.boximg{
    padding: 5px;
    box-shadow: 0 0 5px #ccc;
    border:1px solid #ccc;
    border-radius: 5px;
}
.boximg img{
    width: 250px;
    height: auto;
}

DOM实操-瀑布流-动态设置内容居中

1 获取所有需要操作的元素
2 获取屏幕的宽度
3 获取一个图片元素容器的宽度
4 动态计算页面横向最多可放置的图片数量
5 动态设置样式,让内容左右居中

function waterFlow(){
    var parentContainer = document.getElementById("container");
    var screenWidth = document.documentElement.clientWidth;
    var childWidth = allChild[0].offsetWidth;
    var rowsNum = Math.floor(screenWidth / childWidth);
    parentContainer.style.cssText = "width:" + childWidth * rowsNum + "px;margin:0 auto";
}
waterFlow();

DOM实操-瀑布流-动态设置图片位置

获取一列中最小高度,后续每张图片都是放在一列中最小高度的下面

1 获取第一行图片高度,放入到数组中
2 获取后续图片,放入到数组高度最小的对应图片下面

function
getMinHeightOfCols(allChild,rowsNum){
    var colsHeightArr = [];
    for(var i = 0;i<allChild.length;i++){
        if(i < rowsNum){
            colsHeightArr[i] = allChild[i].offsetHeight;
       }else{
            var minHeightofCols = Math.min.apply(null,colsHeightArr);
            var minHeightOfIndex = colsHeightArr.indexOf(minHeightofCols);
            allChild[i].style.position = "absolute";
            allChild[i].style.top = minHeightofCols + "px";
            allChild[i].style.left = allChild[minHeightOfIndex].offsetLeft + "px";
            colsHeightArr[minHeightOfIndex] = colsHeightArr[minHeightOfIndex] + allChild[i].offsetHeight;
       }
   }
}

DOM实操-瀑布流-页面触底

1 逻辑:滚动高度 + 视口高度 = 文档高度
2 业务:滚动高度 + 视口高度 > 最后一个元素顶部距离顶部高度

function checkReachBottom(){
    var scrollHeight = document.documentElement.scrollTop;
    var pageHeight = document.documentElement.clientHeight;
    var allChild = document.getElementsByClassName("box");
    var lastChildTop = allChild[allChild.length - 1].offsetTop;
    return lastChildTop < pageHeight + scrollHeight ? true : false;
}

DOM实操-瀑布流-上拉加载

1 动态创建元素
2 重新加入瀑布流效果

window.onscroll = function () {
    if (checkReachBottom()) {
      var parentContainer = document.getElementById("container");
        for(var i = 0;i<dataImage.data.length;i++){
            var childBox = document.createElement("div");
          
			childBox.setAttribute("class","box");
			          
			parentContainer.appendChild(childBox);
			var childImgBox = document.createElement("div");
			          
			childImgBox.setAttribute("class","boximg");
			          
			childBox.appendChild(childImgBox);
            var img = document.createElement("img");
            childImgBox.appendChild(img);
       }
        waterFlow();
   }
}

DOM实操-轮播图-页面布局

在这里插入图片描述
轮播图
轮播图是用一套图片以一定时间间隔(如5秒)进行循环播放,一段时间内呈现给用户不同的内容展示方式

轮播图特点

1 自动循环播放
2 指示器聚焦导航

<div class="box">
    <div class="imglist" id="imglist">
        <ul>
            <li class="current"><a href="#"><img src="./img/1.jpg" alt=""></a></li>
            <li><a href="#"><imgsrc="./img/2.jpg" alt=""></a></li>
            <li><a href="#"><imgsrc="./img/3.jpg" alt=""></a></li>
            <li><a href="#"><imgsrc="./img/4.jpg" alt=""></a></li>
            <li><a href="#"><imgsrc="./img/5.jpg" alt=""></a></li>
         </ul>
    </div>
    <div class="btn">
        <span class="leftbtn" id="left"></span>
        <span class="rightbtn" id="right"></span>
    </div>
    <div class="circle" id="circle">
        <ul>
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
</div>
*{
    margin: 0;
    padding: 0;
}
.box{
    width: 672px;
    height: 320px;
    border: 1px solid gray;
    margin: 100px auto;
    position: relative;
}
ul{
  list-style: none;
}
.imglist ul li{
    width: 672px;
    height: 320px;
    position: absolute;
    top:0;
    left: 0;
    display: none;
}
.imglist ul li.current{
    display: block;
}
.btn span{
    width: 55px;
    height: 55px;
    background: url("./images/sohu//slidebtnL.png");
    position: absolute;
    top: 50%;
    margin-top: -27px;
}
.btn span.leftbtn{
    left: 10px;
}
.btn span.rightbtn{
    right: 10px;
    background: url("./images/sohu/slidebtnR.png");
}
.circle{
    position: absolute;
     bottom: 10px;
    right: 10px;
}
.circle ul li{
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.5);
    float: left;
    margin-right: 10px;
}
.circle ul li.current{
    background: rgba(255,255,255,1);
}

DOM实操-轮播图-动态切换

在这里插入图片描述

// 1. 获取元素
var imglis = document.getElementById("imglist").querySelectorAll("li");
var leftBtn = document.getElementById("left");
var rightBtn = document.getElementById("right");
var circlelis = document.getElementById("circle").querySelec
torAll("li");
// idx控制图片显示
var idx = 0;
leftBtn.onclick = function () {
    idx++
    console.log(idx);
    changePic();
}
rightBtn.onclick = function () {
    idx--
    console.log(idx);
    changePic();
}
// 2. 控制页面图片显示与隐藏
function changePic() {
    // idx边界处理
    if (idx > imglis.length - 1) {
        idx = 0;
        }
    if (idx < 0) {
        idx = imglis.length - 1;
   }
    // 先把所有的current都移除,然后给对一个的那个元素添加显示就行了
    for (var i = 0; i < imglis.length; i++)
{
        imglis[i].removeAttribute("class");
   }
    imglis[idx].setAttribute("class","current");
    for (var i = 0; i < circlelis.length;
i++) {
      
circlelis[i].removeAttribute("class");
   }
    // 设置指示器高亮
    circlelis[idx].setAttribute("class", "current")
}
// 点击指示器切换图片
for(var i = 0;i<circlelis.length;i++){
     (function(i){
        circlelis[i].onclick = function(){
            idx = i;
            changePic();
            }
   })(i)
}
// for (var i = 0; i < circlelis.length;
//i++) {
//     // 自定义属性的方式处理
//     circlelis[i].idxx = i;
//     circlelis[i].onclick = function () {
//         // 不就是获取不到i的值
//         idx = this.idxx;
//         changePic();
//     }
// }

DOM实操-放大镜-页面布局

放大镜
通过鼠标滑动,对页面某个部分的区域放大

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initialscale=1.0">
    <title>Document</title>
    <style>
       *{
            margin: 0;
            padding: 0;
       }
        .smallpic{
            width: 450px;
            height: 450px;
            border: 1px solid gray;
            position: absolute;
            top: 100px;
            left: 100px;
       }
        .zoom{
         width: 300px;
            height: 300px;
            background: yellow;
            opacity: 0.5;
            position: absolute;
            top: 0;
            left: 0;
            display: none;
       }
        .bigpic{
            width: 550px;
            height: 550px;
            background:
			url("./images/jd/da.jpg");
            border: 1px solid gray;
            position: absolute;
            top: 100px;
            left: 552px;
            display: none;
       }
    </style>
</head>
<body>
    <div class="smallpic" id="small">
        <img src="./images/jd/xiao.jpg"alt="">
        <div class="zoom" id="zoom"></div>
    </div>
    <div class="bigpic" id="big"></div>
</body>
</html>

DOM实操-放大镜-业务逻辑

var small = document.getElementById("small");
var zoom = document.getElementById("zoom");
var big = document.getElementById("big");
small.onmouseover = function(){
    zoom.style.display = "block";
    big.style.display = "block";
}
small.onmouseout = function(){
    zoom.style.display = "none";
    big.style.display = "none";
}
var rate = 800 / 450;
small.onmousemove = function(e){
    var zoomX = e.clientX - small.offsetLeft - 150;
    var zoomY = e.clientY - small.offsetTop - 150;
    if(zoomX < 0){
        zoomX = 0;
   }
    if(zoomX >= 150){
        zoomX = 150;
   }
    if(zoomY <0){
        zoomY = 0;
   }
    if(zoomY >= 150){
        zoomY = 150;
   }
    zoom.style.left = zoomX + "px";
    zoom.style.top = zoomY + 'px';
    big.style.backgroundPositionX = -zoomX * rate + "px";
    big.style.backgroundPositionY = -zoomY * rate + "px";
}

DOM实操-回到顶部

回到顶部
回到顶部是页面常见效果,一般当页面太长的时候都会给你一个按钮,点击可以回到顶部

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initialscale=1.0">
    <title>Document</title>
    <style>
        div{
            height: 500px;
       }
        #btn{
        width: 35px;
            height: 45px;
            position: fixed;
            right: 50px;
            bottom: 50px;
            background: #333;
            text-decoration: none;
            color: #fff;
            text-align: center;
            padding: 10px;
            display: none;
       }
    </style>
</head>
<body>
    <div>内容1</div>
    <div>内容2</div>
    <div>内容3</div>
    <div>内容4</div>
    <div>内容5</div>
    <div>内容6</div>
    <a href="javaScript:void(0)" id="btn">回到顶部</a>
    <script>
        var btn = document.getElementById("btn");
        var clientHeight = document.documentElement.clientHeight;
        window.onscroll = function(){
            var scrollHeight = document.documentElement.scrollTop;
            if(scrollHeight > clientHeight){
              btn.style.display = "block"
           }else{
                btn.style.display = "none"
           }
       }
        btn.onclick = function(){
          
		document.documentElement.scrollTop = 0; //回到顶部
       }
    </script>
</body>
</html>

浏览器环境概述(BOM)

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐