DOM树
DOM: Document Object Model
使用对象的方式描述对应的html
API 规范,
浏览器中的JS 包含 DOM 通过JS 调用 API 操作浏览器操作 DOM树。
DOM 树:节点(node) 层次,文档节点(document)、元素节点、属性节点、文本节点。 DOM 把一个文档表示为一颗家谱树(父、子、兄弟)
节点遍历
以p节点为参考对象node,
node.parentNode = body
node.firstChild = hello,
node.lastChild = img
node.previousSibling = null
node.nextSibling = div
节点类型
element_node 元素节点(body, p, div, span, img)
text_node 文本节点(hello, mooc, 为专业)
comment_node
document_type_node
元素遍历
p 的第一个元素节点是 em,p的最后一个元素节点是 a
em.nextElementSibling = a,em.previousElementSibling = null
如何兼容浏览器版本的element.children
element.children能够获取元素的元素子节点,但是低版本的ie不支持,如何在低版本的ie上兼容类似的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function getElementChildren (element ) { if (element.children) { return element.children; } else { var list = []; var nodelist = element.childNodes; for (var i = 0 ; i < nodelist.length; i++) { if (nodelist[i].nodeType == 1 ){ list.push(nodelist[i]); } } return list; } }
节点操作 —
使用html表示页面的结构,浏览器读取html,并解析之后,能够生成页面的结构,然后再读取CSS,最后渲染出我们能看到的页面。页面渲染之后,如何修改页面结构。
1 2 3 4 5 <div id ="mydiv" > <span id ="span1" > 1</span > <span id ="span2" > 2</span > <span id ="span3" > 3</span > </div >
1 2 3 4 5 6 7 8 var mydiv = document .querySelector('#mydiv' );mydiv.firstChild; mydiv.firstElementChild; mydiv.lastChild; mydiv.lastElementChild; mydiv.childNodes; mydiv.children;
节点还包括 text 节点,标签与标签之间的文本信息,也算一个结点。 元素节点单指标签。同理:
1 2 3 4 5 var span1Ele = document .querySelector('#span1' ); span1Ele.parentNode; span1Ele.nextSibling; span1Ele.nextElementSibling;
节点方法名:
方法名
返回值类型
说明
hasChildNodes()
Boolean
当前节点是否有子节点
appendChild(node)
Node
往当前节点上添加子节点
removeChild(node)
Node
删除子节点
replaceChild(oldNode, newNode)
Node
替换子节点
insertBefore(newNode, refNode)
Node
在指定节点前插入新结点
小练习:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <span id ="span1" > span1</span > <span id ="span2" > span2</span > <div id ="div1" style ="background: palegreen" > 1</div > <div id ="div2" style ="background: palegoldenrod" > 2</div > <div id ="div3" style ="background: palevioletred" > 3</div > <button onclick ="fun1()" > 把 span1 添加到 div1</button > <button onclick ="fun2()" > 把 span2 添加到 div2</button > <button onclick ="fun3()" > 创建span元素添加到div3</button > <br /> <select id ="character" size ="7" > <option id ="item1" > 刘备</option > <option id ="item2" > 关羽</option > <option id ="item3" > 张飞</option > <option id ="item4" > 赵云</option > </select > <button onclick ="fun4()" > 在关羽之前插入诸葛亮</button > <button onclick ="fun5()" > 把关羽换成魏延</button > <button onclick ="fun6()" > 删除张飞</button >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 function fun1 ( ) { var span1 = document .querySelector('#span1' ); var div1 = document .querySelector('#div1' ); div1.appendChild(span1); } function fun2 ( ) { var span2 = document .querySelector('#span2' ); var div2 = document .querySelector('#div2' ); div2.appendChild(span2); } function fun3 ( ) { var span3 = document .createElement('span' ); span3.innerHTML = "span3" ; span3.id = 'span3' var div3 = document .querySelector('#div3' ); div3.appendChild(span3); } function fun4 ( ) { var sels = document .querySelector('#character' ); for (var childrenKey in sels.children) { var op = sels.children[childrenKey]; if (op.innerHTML == '关羽' ) { var option = document .createElement('option' ); option.id = 'item' + childrenKey; option.innerHTML = "诸葛亮" ; sels.insertBefore(option, op); break ; } } } function fun5 ( ) { var sels = document .querySelector('#character' ); for (var childrenKey in sels.children) { var op = sels.children[childrenKey]; if (op.innerHTML == '关羽' ) { var option = document .createElement('option' ); option.id = 'item' + (parseInt (childrenKey) + 1 ); option.innerHTML = "魏延" ; sels.replaceChild(option, op); break ; } } } function fun6 ( ) { var sels = document .querySelector('#character' ); for (var childrenKey in sels.children) { var op = sels.children[childrenKey]; if (op.innerHTML == '张飞' ) { sels.removeChild(op); break ; } } }
获取节点
通过已获取到的节点的DOM数,可以获取节点
父子关系:
parentNode
firstChild/lastChild/childNodes
childNodes/children
兄弟关系:
previousSibling/nextSibling
previousElementSibling/nextElementSibling
这样获取节点的可维护性差
getElementById, 返回一个元素 getElementsByTagName, 返回集合 返回值是动态的,对节点操作,会影响其取值的变化。
通过这个方法可以获取指定元素下所有的后代元素。
getElementsByClassName, 返回集合 collection,返回的是集合,集合是动态的, 如果删除掉其中的一个值,则collection 中的值也会改变。
通过空格分隔,指定多个类名。和类名的顺序没什么关系。
ie 6 7 8 并不兼容 getElementsByClassName
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 function getElementByClassName (element, classNames ) { if (element.getElementByClassName) { return element.getElementByClassName(classNames); } else { var elements = element.getElementsByTagName('*' ); var result = []; var element, classNameStr, flag; classNames = classNames.split(' ' ); for (var i = 0 ; element = elements[i]; i++) { classNameStr = ' ' + element.className + ' ' ; flag = true ; for (var j = 0 , className; className = classNames[j]; j++) { if (classNameStr.indexOf(' ' + name + '' ) == -1 ) { flag = false ; break ; } } if (flag) { result.push(element); } } return result; } } function hasClassName (element, className ) { return element.className == className; }
querySelector/ALL list = element.querySelector/All(selector)
list 不是动态的,反映在如果获取了节点所有的元素,如果我们删掉了其中一个。list内部的值并未改变。
前者获取第一个符合条件的元素,后者获取所有符合条件的元素。
此时,users 获取到的是 div单个元素 div#users
1 2 3 4 users.querySelectorAll(".user" ) document.querySelectorAll(#users .user");
querySelector 返回的列表是静态的!
live: 动态集合
sole: 单一的
only document: 节点
创建节点
创建节点:
createElement,
element = document.createElement(tagName)
创建指定标签的元素。
设置节点内容
element.textContent 节点及其后代节点的文本内容。ie9 不支持
element.innerText 节点及其后代节点的文本内容。 常用(不规范, ff 不支持)
平台兼容方案:
插入节点
appendChild var achild = element.appendChild(achild);
在指定元素的最末尾,追加元素
insertBefore, var achild = element.insertBefore(achild, referenceChild);
将节点插入到指定元素的前面。
ul.insertBefore(li, ul.firstChild);
删除节点
removeChild,
child = element.removeChild(child)
删除element 指定的子元素
user2.parentNode.removeChild(user2);
innerHTML 提高效率
节点的 HTML 内容,建议仅用于新节点。内容可控,不是用户填写的内容,如果是用户填写的内容也要确保内部没有标签
低版本的ie 内存泄露,
安全问题:
修改属性
每一个html属性对应相应的 DOM 对象属性
HTML attribute -> DOM property
input.id input.type input.className
label.htmlFor = username
属性访问器 来操作对象
读取属性 input.className input[“id”]
属性写
input.value = ‘wwq@163.com ‘
其实是在 标签内加入了 value 属性 并且赋值为 wwq@163.com
input.disabled = true;
input.className = “u-txt” String
input.maxLenth = 10 Number
input.disabled = true Boolean
input.onclick = function onclick(event){} Function
通过属性访问修改的属性,会转会进行类型转换,从字符串 转换到实用对象
用属性访问器来操作对象
通用性比较差, 名字异常
扩展性 比较差
取到的是实用对象,可以直接实用。
用 get / setAttribute 来操作对象
读 var attribute = element.getAttribute(attributeName);
input.getAttribute(“class”) // “u-txt”
写 element.setAttribute(name, value);
input.setAttribute(“value”, “wwq@163.com “);
input.setAttribute(“disabled”, “”);
get / setAttribute 来操作对象 纯粹是字符串的操作
get / setAttribute 来操作对象 特点
仅字符串 通用性好
案例:
为了防止重复点击登录按钮,重复发送请求,要在点击之后,改变登录按钮的样式
两种方式都能进行属性改变,如果是纯字符串操作,可以使用 get/setAttribute 如果是 实用类型,则实用属性访问器
dataset
HTMLElement.dataset
data-* 属性集
用途: 元素上保存数据
例子:
如何实现浏览器兼容版的 element.dataset
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function getDataset (element ) { element.dataset = {}; var attrs = element.attributes; for (var i = 0 ; i < attrs.length; i++) { if (/^data-/ .test(attrs[i].name)) { var key = attrs[i].name.match(/^data-(.+)/ )[1 ]; var value = attrs[i].value; key = key.replace(/-\w/g ,function (match ) { return match.substring(1 ).toUpperCase(); }); element.dataset[key] = value; } } return element.dataset; }
样式操作
js 动态修改样式
CSS 的外部样式链接表:获取元素
获取内部样式:element.sheet
以上两种样式链接表可以通过 document.styleSheets 获取
CSSStyleDeclaration 是CSS属性名和属性值键值对的列表。
获取标签内部样式:element.style
更新样式
标准做法一:style.cssText(这种方式不够好)
标准做法二:更新class
换肤(更换样式表) 一次性更新很多元素
更换样式表:$(‘skin’).href = “skin.summer.css”;
1 2 3 function $ (id ) { return document .getElementById(id); }
获取样式
element.style 对应元素内嵌样式表 这样没办法获取到实际样式
只有设置了内嵌 style 属性的元素,才能通过element.style获取到元素的样式。
通过 window.getComputedStyle() var style = window.getComputedStyle(element, pseudoElt]);
返回 style 是一个只读的 CSSStyleDeclaration 类型的属性
window.getComputedStyle(element).color // “rgb(0, 0, 0)”
获取到实际的颜色
ie9 不支持, ie9 会用element.currentStyle 做兼容
CSS DOM overview(概览)
StyleSheetList[0] 获取到具体样式表 -> CSSStyleSheet
如何实现兼容版的 window-getComputedStyle
1 2 3 4 5 6 7 8 function getStyle (element ) { if (window .getComputedStyle) { return window .getComputedStyle(element); } else if (element.currentStyle) { return element.currentStyle; } }
实现getStyle函数
getStyle函数用于获取元素的实际样式,语法如下:
var cssPropertyValue = getStyle (element, cssPropertyName);
使用示例如下: getStyle(element, “color”) 返回element元素的显示颜色,如:”rgb(0, 0, 0)” getStyle(element, “line-height”) 返回element元素的实际行高,如:”30px” 请实现getStyle函数,要求浏览器兼容。
1 2 3 4 5 6 7 function getStyle (element,attr ) { if (window .getComputedStyle) { return getComputedStyle(element)[attr]; } else { return element.currentStyle[attr]; } }
DOM 事件
什么是 DOM 事件?
点击一个 DOM 事件、键盘按下一个键等等
需要记住的事件属性
onblur 元素失去焦点
onclick 鼠标点击
onchange 文本域改变、用户改变域的内容
JS事件参考手册
小练习:
1 <img id ="img" src ="lady.jpg" width ="400" height ="300" />
1 2 3 4 var imgEle = document .querySelector('#img' );imgEle.onmouseover = function ( ) { this .src = 'supperman.png' ; }
练习1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>Title</title> <script> function checkAll(flag) { var all = document.getElementsByName('hobby') var checkAll = document.querySelector('#checkAll') checkAll.checked = flag; for (var allKey in all) { all[allKey].checked = flag; } } function checkUnAll() { var all = document.getElementsByName('hobby') var checkAll = document.querySelector('#checkAll') var flag = true; for (var allKey in all) { all[allKey].checked = !all[allKey].checked if (all[allKey].checked == false) { flag = false; } } checkAll.checked = flag } </ script></head> <body> 请选择你的爱好: <input type="checkbox" onchange="checkChange()" id="checkAll"/ >全选/全不选 <br/><div> <input type="checkbox" name="hobby" />JAVA <input type="checkbox" name="hobby" />打篮球 <input type="checkbox" name="hobby" />上网 <input type="checkbox" name="hobby" />撩妹 </div> <div> <input type="button" id="btn_checkAll" onclick="checkAll(true)" value="全选"/ > <input type="button" onclick="javascript:checkAll(false)" value="全不选" /> <input type="button" onclick="checkUnAll()" value="反选" /> </div> </ body></html>
练习2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>Title</title> <script> function moveSelected(id1, id2) { var selectSrc = document.querySelector('#' + id1); var selectDir = document.querySelector('#' + id2); var options = selectSrc.selectedOptions; while (options.length > 0) { selectDir.appendChild(options[0]) } } function moveAll(id1, id2) { var selectSrc = document.querySelector('#' + id1); var selectDir = document.querySelector('#' + id2); var options = selectSrc.options; while (options.length > 0) { var ele = selectSrc.options[0] selectDir.appendChild(ele) } } </ script></head> <body> <table border="1"> <tr> <td width="50"> <select id="select1" size="10" multiple="multiple"> <option value="选项1">选项1</ option> <option value="选项2" >选项2 </option> <option value="选项3">选项3</ option> <option value="选项4" >选项4 </option> <option value="选项5">选项5</ option> <option value="选项6" >选项6 </option> <option value="选项7">选项7</ option> <option value="选项8" >选项8 </option> <option value="选项9">选项9</ option> </select> </ td> <td align="center" > <input type="button" onclick="moveSelected('select1', 'select2')" value="-->" /><br /> <input type="button" onclick="moveAll('select1', 'select2')" value="==>" /><br /> <input type="button" onclick="moveSelected('select2', 'select1')" value="<--" /><br /> <input type="button" onclick="moveAll('select2', 'select1')" value="<==" /> </td> <td width="50"> <select id="select2" size="10" multiple="multiple"> </ select> </td> </ tr></table> </ body></html>
jqury 版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>Title</title> <script src="static/ jquery/jquery-1.11 .3 .min.js"></script> <script> $(function () { var checkHobbyState = function() { // 只有4个爱好选中时 修改全选的标识 var sum = true; $('input[name=hobby]').each(function (index, domEle) { sum = sum && $(domEle).prop('checked') }) $('#checkAll').prop('checked', sum) } $('#checkAll').change(function () { $('input[name=hobby]').prop('checked', $(this).prop('checked')) }) $('#btn_checkAll').click(function () { $('input[name=hobby]').prop('checked', true) checkHobbyState() }) $('#btn_checkUnAll').click(function () { $('input[name=hobby]').prop('checked', false) checkHobbyState() }) $('#btn_checkReverse').click(function () { $('input[name=hobby]').prop('checked', function (index, checkedValue) { return !checkedValue }) checkHobbyState() }) }) // foreach 底层原理 Array.prototype.foreach2 = function (fn) { for (var i = 0; i < this.length; i++) { fn(this[i], i, this) } } var arr = ['1', '2', '3'] arr.forEach(function (value, index) { console.log(value); console.log(index); }) // map 底层原理 Array.prototype.map2 = function (fn) { var newArr = [] for (var i = 0; i < this.length; i++) { var result = fn(this[i], i, this) newArr.push(result) } return newArr } var newA2 = arr.map2(function (value, index, array) { return '1' + value }) console.log(newA2); </script> </head> <body> 请选择你的爱好: <input type=" checkbox" id=" checkAll"/>全选/全不选 <br/> <div> <input type=" checkbox" name=" hobby"/>JAVA <input type=" checkbox" name=" hobby"/>打篮球 <input type=" checkbox" name=" hobby"/>上网 <input type=" checkbox" name=" hobby"/>撩妹 </div> <div> <input type=" button" id=" btn_checkAll" value=" 全选"/> <input type=" button" id=" btn_checkUnAll" value=" 全不选"/> <input type=" button" id=" btn_checkReverse" value=" 反选"/> </div> </body> </html>
练习3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>Title</title> <script> window.onload = function () { var removeAll = document.querySelector('#btn_removeAll'); removeAll.onclick = function () { var ele = document.querySelector('#userTbody') ele.innerHTML = '' } var trId = 1; var btn_submit = document.querySelector('#btn_submit') btn_submit.onclick = function () { / / 找到所有 input 输入文本值 var username = document.querySelector('#username').value var email = document.querySelector('#email').value var tel = document.querySelector('#tel').value / / 创建 tr td 并 td 加到 tr 中 var usernameTdEle = document.createElement('td') usernameTdEle.innerHTML = username var emailTdEle = document.createElement('td') emailTdEle.innerHTML = email var telTdEle = document.createElement('td') telTdEle.innerHTML = tel var optionTdEle = document.createElement('td') optionTdEle.innerHTML = '<a href="javascript:delRow(\'tr' + trId + '\')">删除</ a>' var trEle = document.createElement(' tr') trEle.id = ' tr' + trId; trId++ trEle.appendChild(usernameTdEle) trEle.appendChild(emailTdEle) trEle.appendChild(telTdEle) trEle.appendChild(optionTdEle) // 把 tr 加到 tbody 中 var tbody = document.querySelector('#userTbody') tbody.appendChild(trEle) } } function delRow (id ) { var removeAll = document .querySelector('#' + id); removeAll.parentNode.removeChild(removeAll); } </script> </ head><body> <form name="userForm" > <center> 用户录入<br/> 用户名:<input id="username" name="username" type="text" size="15" /> E-mail:<input id="email" name="email" type="text" size="15" > 电话:<input id="tel" name="tel" type="text" size="15" > <input type="button" value="添加" id="btn_submit" > <input type="button" value="删除所有" id="btn_removeAll" > </center> </ form><hr/> <table border="1" align="center" cellpadding="0" cellspacing="0" width="400" > <thead> <tr> <th>用户名</th> <th>E-mail</ th> <th>电话</th> <th>操作</ th> </tr> </ thead> <tbody id="userTbody" > <tr id="tr1" > <td>张无忌</td> <td>wujizhang@163.com</ td> <td>18212345678 </td> <td><a href="javascript:delRow('tr1')">删除</ a></td > </tr> </ tbody></table> </ body></html>
jquery 版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>Title</title> <script src="static/ jquery/jquery-1.11 .3 .min.js"></script> <script> $(function () { var trId = 2 $('#btn_removeAll').click(function () { $('#userTbody').empty() }) $('#btn_submit').click(function () { // 找到所有 input 输入文本值 var username = $('#username').val() var email = $('#email').val() var tel = $('#tel').val() // 模板字符串 var a = ` <tr id=" tr${trId}"> <td>${username}</td> <td>${email}</td> <td>${tel}</td> <td><a href=" javascript:delRow('tr${trId}' )">删除</a></td> </tr> `; $('#userTbody').append(a) trId ++; }) }) function delRow(id) { $('#' + id).remove(); } </script> </head> <body> <form name=" userForm"> <center> 用户录入<br/> 用户名:<input id=" username" name=" username" type=" text" size=" 15 "/> E-mail:<input id=" email" name=" email" type=" text" size=" 15 "> 电话:<input id=" tel" name=" tel" type=" text" size=" 15 "> <input type=" button" value=" 添加" id=" btn_submit"> <input type=" button" value=" 删除所有" id=" btn_removeAll"> </center> </form> <hr/> <table border=" 1 " align=" center" cellpadding=" 0 " cellspacing=" 0 " width=" 400 "> <thead> <tr> <th>用户名</th> <th>E-mail</th> <th>电话</th> <th>操作</th> </tr> </thead> <tbody id=" userTbody"> <tr id=" tr1"> <td>张无忌</td> <td>wujizhang@163.com</td> <td>18212345678</td> <td><a href=" javascript:delRow('tr1' )">删除</a></td> </tr> </tbody> </table> </body> </html>
事件流
会从事件的最顶端,window 开始往下 捕获到触发事件节点的父元素,即 p 元素
事件触发过程。
从事件响应的起 冒泡的 window 对象。
有些事件没有冒泡过程, 一些低版本浏览器没有 capture 过程。
事件注册与触发
事件注册 、事件触发、 事件取消注册
事件注册 eventTarget.addEventListener(type, listener[, useCapture])
使用第二种事件注册方法,有个弊端,只能注册一个函数。实际上可以有多个函数响应该事件。
取消事件注册 eventTarget.removeEventListener(type, listener[, useCapture])
事件触发 eventTarget.dispatchEvent(type)
浏览器兼容 ie6、7、8 没有采用该标准
attchEvent/detachEvent
fireEvent(e)
js 的 addEventListener 和 removeEventListener 的兼容
事件对象
ie 的 低版本:不是通过函数传入 event对象,而是将事件对象放在 window.event中,兼容方式:
属性
type
target(sourceElement)
currentTarget(当前处理事件节点),有可能处理函数是注册在 target 父节点上
方法
stopPropagation 阻止传播,不想继续冒泡了(w3c)
event.cancelBubble = true(IE)
stopImmediatePropagation 阻止冒泡
阻止事件传播到父节点
阻止当前节点的后续事件(在我后面注册的事件不会传播)
preventDefault 阻止默认行为(w3c)
event.returnValue = false(IE)
阻止默认行为,比如点击链接,会默认打开链接。可以使用该方法阻止事件响应。
事件分类
MouseEvent
mouseover、mouseout 与 mouseenter、mouseleave 的区别
加入 div 有子元素, 我们鼠标离开 div 元素 进入到 div 中的子元素上,都会触发 mouseover 、 mouseout
mouseenter、mouseleave 只有进入这个元素就会触发,进入该元素的子元素不会触发。而出这个 div 元素。将 div 看成一个整体,进入或移出这个整体会触发。
属性
clientX, clientY
screenX, screenY
ctrlKey, shiftKey, altKey, metaKey
如果事件触发时,这几个键是按下去的,则这些属性为 true 否则为false
button(0,1,2)分别代表按下鼠标的键是左键还是右键
MouseEvent 顺序
从元素A上方移过:
mousemove -> moseover(A) -> mouseenter(A) -> mousemove(A)(多次) -> mouseout(A) -> mouseleave(A)
点击元素
mousedown -> [mousemove] -> mouseup -> click
例子 拖拽div
WheelEvent对象 事件类型: wheel 是否冒泡: YES 元素:Element 默认事件:scroll or zoom document 元素: div
属性:
deltaMode(delta值的单位)
deltaX
deltaY
deltaZ
x y z 轴上的偏移量
FocusEvent
属性:
relatedTarget 当一个元素失去焦点时,获得焦点的元素就是 relatedTarget,当一个元素获得焦点时,失去焦点的元素就是 relatedTarget。
ie 兼容:
onpropertychange
KeyboardEvent 处理键盘事件 比如回车键,等
属性:
key: 你按下的什么键 字符串
code:按键码
ctrlKey、shiftKey、altKey、metaKey 用来标识这些键有没有按下去
repeat: 持续按一个键,值是true
keyCode:获取键盘的键的ASK码
charCode:
which
Event 其他事件类型
依赖网络加载的事件,加载完成时会触发,
unload 指 页面退出的时候出发
error 出现在加载错误
selected 通常 input textarea 被选择了 会触发
abort 退出事件,Window image上,比如图片加载时,按了 esc 会触发
window对象
load 当页面上所有的请求都完成时,会触发 load
unload 当文档退出的时候,比如关闭当前页面,离开当前页面
error 浏览器加载异常
abort 离开页面
image
load 图片加载完成
error 图片加载异常
abort 当图片加载时,按esc 会触发
一般这样通用:
如果指定图片加载不到,会显示默认图片。
UIEvent resize 通常在修改窗体大小的时候,修改浏览器窗体大小,iframe窗体大小
scroll 指页面发生滚动时触发。元素上触发会冒泡
元素上触发scroll会冒泡,document上触发Scroll 不会冒泡
事件代理
将事件注册到元素的父节点上,对于ul li 一组标签来说,将事件注册到父元素上,这样简化事件注册。
触发事件的方式
为什么 JavaScript 中的函数需要用 window.onload 包起来?
window.onload 方法的作用是在页面的所有元素都加载完毕后才会触发,包括图片。当连接质量不好的时候,会导致该方法触发延迟。当然你也可以在 body 后写 script 代码,但是这样不符合习惯。
1 <button id ="btn" > 点击</button >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 window .onload = function ( ) { var btn = document .querySelector('#btn' ); btn.onclick = function ( ) { console .log(1 ); }; btn.addEventListener('click' , function ( ) { console .log(2 ); }) var listener = function ( ) { console .log(3 ); } btn.addEventListener('click' , listener); btn.removeEventListener('click' , listener); function addEvent (btn, eventName, func ) { if (btn.attachEvent) { btn.attachEvent('on' , eventName, func); } else { btn.addEventListener(eventName, func); } } }