JavaScript:DOM模型
DOM概述DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个JavaScript 对象,从而可以用脚本进行各种操作(比如对元素增删内容)浏览器会根据 DOM 模型,将结构化文档HTML解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口DOM
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.doctypedocument.doctype
,指向 <DOCTYPE>
节点,即文档类型(Document Type Declaration,简写DTD)节点。HTML 的文档类型节点,一般写成 <!DOCTYPE html>
。如果网页没有声明 DTD
,该属性返回null
var doctype = document.doctype;
doctype // "<!DOCTYPE html>"
document.documentElementdocument.documentElement
属性返回当前文档的根节点(root),一般是 <html>
节点
document.documentElement
document.body,document.headdocument.body
属性指向 <body>
节点,document.head
属性指向<head>
节点
document.body;
document.head;
document.formsdocument.forms
属性返回所有 <form>
表单节点
var selectForms = document.forms;
document.imagesdocument.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.scriptsdocument.scripts
属性返回所有 <script>
节点
var scripts = document.scripts;
if (scripts.length !== 0 ) {
console.log('当前网页有脚本');
}
document.domaindocument.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.idElement.id
属性返回指定元素的 id
属性,该属性可读写
// HTML 代码为 <p id="foo">
var p = document.querySelector('p');
p.id // "foo"
Element.classNameclassName
属性用来读写当前元素节点的 class
属性。它的值是一个字符串,每个 class
之间用空格分割
// HTML 代码 <div class="one two three"
id ="myDiv"></div>
var div = document.getElementById('myDiv');
div.className
Element.classListclassList
对象有下列方法
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.innerHTMLElement.innerHTML
属性返回一个字符串,等同于该元素包含的所有HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括 <HTML>
和 <body>
元素
el.innerHTML = '';
Element.innerTextinnerText
和 innerHTML
类似,不同的是 innerText
无法识别元素,会直接渲染成字符串
Element获取元素位置一
Element.clientHeight,Element.clientWidthElement.clientHeight
属性返回一个整数值,表示元素节点的 CSS 高度(单位像素),只对块级元素生效,对于行内元素返回 0 。如果块级元素没有设置 CSS 高度,则返回实际高度
除了元素本身的高度,它还包括 padding
部分,但是不包括 border
、margin
。如果有水平滚动条,还要减去水平滚动条的高度。注意,这个值始终是整数,如果是小数会被四舍五入。
Element.clientWidth
属性返回元素节点的 CSS 宽度,同样只对块级元素有效,也是只包括元素本身的宽度和 padding
,如果有垂直滚动条,还要减去垂直滚动条的宽度。
document.documentElement
的 clientHeight
属性,返回当前视口的高度(即浏览器窗口的高度)。 document.body
的高度则是网页的实际高度。
// 视口高度
document.documentElement.clientHeight
// 网页总高度
document.body.clientHeight
Element.clientLeft,Element.clientTopElement.clientLeft
属性等于元素节点左边框(left border)的宽度(单位像素),不包括左侧的 padding
和 margin
。如果没有设置左边框,或者
是行内元素( display: inline
),该属性返回 0 。该属性总是返回整数值,如果是小数,会四舍五入
Element.clientTop
属性等于网页元素顶部边框的高度(单位像素)
var box = document.getElementById("box");
console.log(box.clientLeft);
console.log(box.clientTop);
Element.scrollHeight,Element.scrollWidthElement.scrollHeight
属性返回一个整数值(小数会四舍五入),表示当前元素的总高度(单位像素),它包括 padding
,但是不包括 border
、margin
以及水平滚动条的高度(如果有水平滚动条的话)
Element.scrollWidth
属性表示当前元素的总宽度(单位像素),其他地方都与 scrollHeight
属性类似。这两个属性只读
整张网页的总高度可以从document.documentElement
或 document.body
上读取
// 返回网页的总高度
document.documentElement.scrollHeight
document.body.scrollHeight
Element获取元素位置二
Element.scrollLeft,Element.scrollTopElement.scrollLeft
属性表示当前元素的水平滚动条向右侧滚动的像素数量, Element.scrollTop
属性表示当前元素的垂直滚动条向下滚动的像素数量。对于那些没有滚动条的网页元素,这两个属性总是等于0
如果要查看整张网页的水平的和垂直的滚动距离,要从document.documentElement
元素上读取
document.documentElement.scrollLeft
document.documentElement.scrollTop
Element.offsetHeight,Element.offsetWidthElement.offsetHeight
属性返回一个整数,表示元素的 CSS 垂直高度(单位像素),包括元素本身的高度、padding
和 border
,以及水平滚动条的高度(如果存在滚动条)。
Element.offsetWidth
属性表示元素的 CSS 水平宽度(单位像素),其他都与 Element.offsetHeight
一致。
这两个属性都是只读属性,只比Element.clientHeight
和 Element.clientWidth
多了
边框的高度或宽度。如果元素的 CSS 设为不可见(比如 display:none;
),则返回 0
Element.offsetLeft,Element.offsetTopElement.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节点属性
datadata
属性用来设置或读取文本节点的内容
// 读取文本内容
document.querySelector('p').firstChild.data
// 设置文本内容
document.querySelector('p').firstChild.data = 'Hello World';
lengthlength
属性返回当前文本节点的文本长度
(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 节点属性_nodeValuenodeValue
属性返回一个字符串,表示当前节点本身的文本值,该属性可读写
// <div id="box">hello world</div>
var box = document.getElementById('box');
box.nodeValue // null
box.firstChild.nodeValue // "hello world"
Node 节点属性_textContenttextContent
属性返回当前节点和它的所有后代节点的文本内容
// <div id="box">This is <span>some</span>
text</div>
document.getElementById('box').textContent
// This is some text
Node 节点属性_nextSiblingNode.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 节点属性_previousSiblingpreviousSibling
属性返回当前节点前面的,距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回 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 节点属性_parentNodeparentNode
属性返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)和文档片段节(documentfragment)
if (node.parentNode) {
node.parentNode.removeChild(node);
}
Node 节点属性_firstChild/lastChildfirstChild
属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回 null
// <p id="p1"><span>First span</span></p>
var p1 = document.getElementById('p1');
p1.firstChild.nodeName // "SPAN"
lastChild
属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回 null
。用法与 firstChild
属性相同
Node 节点属性_childNodeschildNodes
属性返回一个类似数组的对象( 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
内部的一个子节点referenceNode
。 newNode
将插在 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.currentTargetEvent.currentTarget
属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点
btn.onclick = function(e){
console.log(e.currentTarget);
}
Event.targetEvent.target
属性返回原始触发事件的那个节点,即事件最初发生的节点。事件传播过程中,不同节点的监听函数内部的Event.target
与Event.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.typeEvent.type
属性返回一个字符串,表示事件类型。事件的类型是在生成事件的时候。该属性只读
Event对象方法
1 Event.preventDefault()
2 Event.stopPropagation()
Event.preventDefaultEvent.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
:按下键盘时触发。
2keypress
:按下有值的键时触发,即按下 Ctrl、Alt、Shift、Meta 这样无值的键,这个事件不会触 发。对于有值的键,按下时先触发keydown事件,再触发这个事件。
3keyup
:松开键盘时触发该事件
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
属性返回发生触摸的元素节点
2touchend
:用户不再接触触摸屏时触发
3touchmove
:用户移动触摸点时触发
4touchcancel
:系统取消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>

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