系统带你学习 WebAPIs 第三讲
Web APIs
本篇學(xué)習(xí)目標(biāo):
能夠使用removeChild()方法刪除節(jié)點(diǎn)
能夠完成動(dòng)態(tài)生成表格案例
能夠使用傳統(tǒng)方式和監(jiān)聽方式給元素注冊(cè)事件
能夠說出事件流執(zhí)行的三個(gè)階段
能夠在事件處理函數(shù)中獲取事件對(duì)象
能夠使用事件對(duì)象取消默認(rèn)行為
能夠使用事件對(duì)象阻止事件冒泡
能夠使用事件對(duì)象獲取鼠標(biāo)的位置
能夠完成跟隨鼠標(biāo)的天使案例
1.1. 節(jié)點(diǎn)操作
1.1.1 刪除節(jié)點(diǎn)
node.removeChild() 方法從 node節(jié)點(diǎn)中刪除一個(gè)子節(jié)點(diǎn),返回刪除的節(jié)點(diǎn)。
<button>刪除</button><ul><li>熊大</li><li>熊二</li><li>光頭強(qiáng)</li></ul><script>// 1.獲取元素var ul = document.querySelector('ul');var btn = document.querySelector('button');// 2. 刪除元素 node.removeChild(child)// ul.removeChild(ul.children[0]);// 3. 點(diǎn)擊按鈕依次刪除里面的孩子btn.onclick = function() {if (ul.children.length == 0) {this.disabled = true;} else {ul.removeChild(ul.children[0]);}}</script>1.1.2 案例:刪除留言
<textarea name="" id=""></textarea><button>發(fā)布</button><ul></ul><script>// 1. 獲取元素var btn = document.querySelector('button');var text = document.querySelector('textarea');var ul = document.querySelector('ul');// 2. 注冊(cè)事件btn.onclick = function() {if (text.value == '') {alert('您沒有輸入內(nèi)容');return false;} else {// console.log(text.value);// (1) 創(chuàng)建元素var li = document.createElement('li');// 先有l(wèi)i 才能賦值li.innerHTML = text.value + "<a href='javascript:;'>刪除</a>";// (2) 添加元素// ul.appendChild(li);ul.insertBefore(li, ul.children[0]);// (3) 刪除元素 刪除的是當(dāng)前鏈接的li 它的父親var as = document.querySelectorAll('a');for (var i = 0; i < as.length; i++) {as[i].onclick = function() {// 刪除的是 li 當(dāng)前a所在的li this.parentNode;ul.removeChild(this.parentNode);}}}}</script>1.1.3 復(fù)制(克隆)節(jié)點(diǎn)
<ul><li>1111</li><li>2</li><li>3</li></ul><script>var ul = document.querySelector('ul');// 1. node.cloneNode(); 括號(hào)為空或者里面是false 淺拷貝 只復(fù)制標(biāo)簽不復(fù)制里面的內(nèi)容// 2. node.cloneNode(true); 括號(hào)為true 深拷貝 復(fù)制標(biāo)簽復(fù)制里面的內(nèi)容var lili = ul.children[0].cloneNode(true);ul.appendChild(lili);</script>1.1.4 案例:動(dòng)態(tài)生成表格
<script>// 1.先去準(zhǔn)備好學(xué)生的數(shù)據(jù)var datas = [{name: '魏瓔珞',subject: 'JavaScript',score: 100}, {name: '弘歷',subject: 'JavaScript',score: 98}, {name: '傅恒',subject: 'JavaScript',score: 99}, {name: '明玉',subject: 'JavaScript',score: 88}, {name: '大豬蹄子',subject: 'JavaScript',score: 0}];// 2. 往tbody 里面創(chuàng)建行: 有幾個(gè)人(通過數(shù)組的長(zhǎng)度)我們就創(chuàng)建幾行var tbody = document.querySelector('tbody');// 遍歷數(shù)組for (var i = 0; i < datas.length; i++) { // 1. 創(chuàng)建 tr行var tr = document.createElement('tr');tbody.appendChild(tr);// 2. 行里面創(chuàng)建單元格td 單元格的數(shù)量取決于每個(gè)對(duì)象里面的屬性個(gè)數(shù) // 使用for in遍歷學(xué)生對(duì)象for (var k in datas[i]) { // 創(chuàng)建單元格 var td = document.createElement('td');// 把對(duì)象里面的屬性值 datas[i][k] 給 td td.innerHTML = datas[i][k];tr.appendChild(td);}// 3. 創(chuàng)建有刪除2個(gè)字的單元格 var td = document.createElement('td');td.innerHTML = '<a href="javascript:;">刪除 </a>';tr.appendChild(td);}// 4. 刪除操作 開始 var as = document.querySelectorAll('a');for (var i = 0; i < as.length; i++) {as[i].onclick = function() {// 點(diǎn)擊a 刪除 當(dāng)前a 所在的行(鏈接的爸爸的爸爸) node.removeChild(child) tbody.removeChild(this.parentNode.parentNode)}}</script>1.1.5 創(chuàng)建元素的三種方式
<script>// 三種創(chuàng)建元素方式區(qū)別 // 1. document.write() 創(chuàng)建元素 如果頁(yè)面文檔流加載完畢,再調(diào)用這句話會(huì)導(dǎo)致頁(yè)面重繪var btn = document.querySelector('button');btn.onclick = function() {document.write('<div>123</div>');}// 2. innerHTML 創(chuàng)建元素var inner = document.querySelector('.inner');for (var i = 0; i <= 100; i++) {inner.innerHTML += '<a href="#">百度</a>'}var arr = [];for (var i = 0; i <= 100; i++) {arr.push('<a href="#">百度</a>');}inner.innerHTML = arr.join('');// 3. document.createElement() 創(chuàng)建元素var create = document.querySelector('.create');for (var i = 0; i <= 100; i++) {var a = document.createElement('a');create.appendChild(a);}</script>1.1.6 innerTHML和createElement效率對(duì)比
innerHTML字符串拼接方式(效率低)
<script>function fn() {var d1 = +new Date();var str = '';for (var i = 0; i < 1000; i++) {document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';}var d2 = +new Date();console.log(d2 - d1);}fn(); </script>createElement方式(效率一般)
<script>function fn() {var d1 = +new Date();for (var i = 0; i < 1000; i++) {var div = document.createElement('div');div.style.width = '100px';div.style.height = '2px';div.style.border = '1px solid red';document.body.appendChild(div);}var d2 = +new Date();console.log(d2 - d1);}fn(); </script>innerHTML數(shù)組方式(效率高)
<script>function fn() {var d1 = +new Date();var array = [];for (var i = 0; i < 1000; i++) {array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');}document.body.innerHTML = array.join('');var d2 = +new Date();console.log(d2 - d1);}fn(); </script>1.2. DOM的核心總結(jié)
關(guān)于dom操作,我們主要針對(duì)于元素的操作。主要有創(chuàng)建、增、刪、改、查、屬性操作、事件操作。
1.2.1. 創(chuàng)建
1.2.2. 增加
1.2.3. 刪
1.2.4. 改
1.2.5. 查
1.2.6. 屬性操作
1.3. 事件高級(jí)
1.3.1. 注冊(cè)事件(2種方式)
案例演示:
<body><div class="box"></div><button id="btn">事件</button><script>var btn=document.querySelector('#btn')var box=document.querySelector('.box')// 采用onclick 方式綁定單擊事件btn.onclick=function(){box.style.width='200px'}// 只有第2個(gè)事件起作用btn.onclick=function(){box.style.height='200px'}// 使用 addeventlistener 方式注冊(cè)事件// btn.addEventListener('click',function(){// box.style.width='200px'// })// btn.addEventListener('click',function(){// box.style.height='200px'// })</script>1.3.2 事件監(jiān)聽
addEventListener()事件監(jiān)聽(IE9以后支持)
eventTarget.addEventListener()方法將指定的監(jiān)聽器注冊(cè)到 eventTarget(目標(biāo)對(duì)象)上,當(dāng)該對(duì)象觸發(fā)指定的事件時(shí),就會(huì)執(zhí)行事件處理函數(shù)。
attacheEvent()事件監(jiān)聽(IE678支持)
? eventTarget.attachEvent()方法將指定的監(jiān)聽器注冊(cè)到 eventTarget(目標(biāo)對(duì)象) 上,當(dāng)該對(duì)象觸發(fā)指定的事件時(shí),指定的回調(diào)函數(shù)就會(huì)被執(zhí)行。
事件監(jiān)聽兼容性解決方案
封裝一個(gè)函數(shù),函數(shù)中判斷瀏覽器的類型:
1.3.3. 刪除事件(解綁事件)
<div>1</div><div>2</div><div>3</div><script>var divs = document.querySelectorAll('div');divs[0].onclick = function() {alert(11);// 1. 傳統(tǒng)方式刪除事件divs[0].onclick = null;}// 2. removeEventListener 刪除事件divs[1].addEventListener('click', fn) // 里面的fn 不需要調(diào)用加小括號(hào)function fn() {alert(22);divs[1].removeEventListener('click', fn);}// 3. detachEventdivs[2].attachEvent('onclick', fn1);function fn1() {alert(33);divs[2].detachEvent('onclick', fn1);}</script>**刪除事件兼容性解決方案 **
1.3.4. DOM事件流
html中的標(biāo)簽都是相互嵌套的,我們可以將元素想象成一個(gè)盒子裝一個(gè)盒子,document是最外面的大盒子。 當(dāng)你單擊一個(gè)div時(shí),同時(shí)你也單擊了div的父元素,甚至整個(gè)頁(yè)面。那么是先執(zhí)行父元素的單擊事件,還是先執(zhí)行div的單擊事件 ???比如:我們給頁(yè)面中的一個(gè)div注冊(cè)了單擊事件,當(dāng)你單擊了div時(shí),也就單擊了body,單擊了html,單擊了document。
當(dāng)時(shí)的2大瀏覽器霸主誰也不服誰! IE 提出從目標(biāo)元素開始,然后一層一層向外接收事件并響應(yīng),也就是冒泡型事件流。 Netscape(網(wǎng)景公司)提出從最外層開始,然后一層一層向內(nèi)接收事件并響應(yīng),也就是捕獲型事件流。江湖紛爭(zhēng),武林盟主也腦殼疼!!!最終,w3c 采用折中的方式,平息了戰(zhàn)火,制定了統(tǒng)一的標(biāo)準(zhǔn) —--— 先捕獲再冒泡。 現(xiàn)代瀏覽器都遵循了此標(biāo)準(zhǔn),所以當(dāng)事件發(fā)生時(shí),會(huì)經(jīng)歷3個(gè)階段。 網(wǎng)景雖死,精神永存!DOM 事件流會(huì)經(jīng)歷3個(gè)階段:
捕獲階段
當(dāng)前目標(biāo)階段
冒泡階段
? 我們向水里面扔一塊石頭,首先它會(huì)有一個(gè)下降的過程,這個(gè)過程就可以理解為從最頂層向事件發(fā)生的最具體元素(目標(biāo)點(diǎn))的捕獲過程;之后會(huì)產(chǎn)生泡泡,會(huì)在最低點(diǎn)( 最具體元素)之后漂浮到水面上,這個(gè)過程相當(dāng)于事件冒泡。
事件冒泡
<div class="father"><div class="son">son盒子</div></div><script>// onclick 和 attachEvent(ie) 在冒泡階段觸發(fā)// 冒泡階段 如果addEventListener 第三個(gè)參數(shù)是 false 或者 省略 // son -> father ->body -> html -> documentvar son = document.querySelector('.son');// 給son注冊(cè)單擊事件son.addEventListener('click', function() {alert('son');}, false);// 給father注冊(cè)單擊事件var father = document.querySelector('.father');father.addEventListener('click', function() {alert('father');}, false);// 給document注冊(cè)單擊事件,省略第3個(gè)參數(shù)document.addEventListener('click', function() {alert('document');})</script>事件捕獲
<div class="father"><div class="son">son盒子</div></div><script>// 如果addEventListener() 第三個(gè)參數(shù)是 true 那么在捕獲階段觸發(fā)// document -> html -> body -> father -> sonvar son = document.querySelector('.son');// 給son注冊(cè)單擊事件,第3個(gè)參數(shù)為trueson.addEventListener('click', function() {alert('son');}, true);var father = document.querySelector('.father');// 給father注冊(cè)單擊事件,第3個(gè)參數(shù)為truefather.addEventListener('click', function() {alert('father');}, true);// 給document注冊(cè)單擊事件,第3個(gè)參數(shù)為truedocument.addEventListener('click', function() {alert('document');}, true)</script>1.3.5. 事件對(duì)象
什么是事件對(duì)象
事件發(fā)生后,跟事件相關(guān)的一系列信息數(shù)據(jù)的集合都放到這個(gè)對(duì)象里面,這個(gè)對(duì)象就是事件對(duì)象。
比如:
誰綁定了這個(gè)事件。
鼠標(biāo)觸發(fā)事件的話,會(huì)得到鼠標(biāo)的相關(guān)信息,如鼠標(biāo)位置。
鍵盤觸發(fā)事件的話,會(huì)得到鍵盤的相關(guān)信息,如按了哪個(gè)鍵。
事件對(duì)象的使用
事件觸發(fā)發(fā)生時(shí)就會(huì)產(chǎn)生事件對(duì)象,并且系統(tǒng)會(huì)以實(shí)參的形式傳給事件處理函數(shù)。
所以,在事件處理函數(shù)中聲明1個(gè)形參用來接收事件對(duì)象。
事件對(duì)象的兼容性處理
事件對(duì)象本身的獲取存在兼容問題:
標(biāo)準(zhǔn)瀏覽器中是瀏覽器給方法傳遞的參數(shù),只需要定義形參 e 就可以獲取到。
在 IE6~8 中,瀏覽器不會(huì)給方法傳遞參數(shù),如果需要的話,需要到 window.event 中獲取查找。
事件對(duì)象的屬性和方法
代碼示例
btn.onclick=function(e){e=e || window.event console.log(e.target || e.srcElement.outerHTML) }e.target 和 this 的區(qū)別
-
this 是事件綁定的元素(綁定這個(gè)事件處理函數(shù)的元素) 。
-
e.target 是事件觸發(fā)的元素。
事件冒泡下的e.target和this
<ul><li>abc</li><li>abc</li><li>abc</li></ul><script>var ul = document.querySelector('ul');ul.addEventListener('click', function(e) {// 我們給ul 綁定了事件 那么this 就指向ul console.log(this); // ul// e.target 觸發(fā)了事件的對(duì)象 我們點(diǎn)擊的是li e.target 指向的就是liconsole.log(e.target); // li});</script>1.3.6 阻止默認(rèn)行為
html中一些標(biāo)簽有默認(rèn)行為,例如a標(biāo)簽被單擊后,默認(rèn)會(huì)進(jìn)行頁(yè)面跳轉(zhuǎn)。
<a href="http://www.baidu.com">百度</a><script>// 2. 阻止默認(rèn)行為 讓鏈接不跳轉(zhuǎn) var a = document.querySelector('a');a.addEventListener('click', function(e) {e.preventDefault(); // dom 標(biāo)準(zhǔn)寫法});// 3. 傳統(tǒng)的注冊(cè)方式document.querySelector('a').onclick=function(e){e=e||window.eventif(e.preventDefault){e.preventDefault()} e.returnValue=false// 或者上面兩種方式都不使用,直接使用下面代碼也可以,沒有兼容問題// 說說這種方法有什么問題// return false}</script>1.3.7 阻止事件冒泡
事件冒泡本身的特性,會(huì)帶來壞處,也會(huì)帶來好處。
<div class="father"><div class="son">son兒子</div></div><script>var son = document.querySelector('.son');// 給son注冊(cè)單擊事件son.addEventListener('click', function(e) {alert('son');e.stopPropagation(); // stop 停止 Propagation 傳播window.event.cancelBubble = true; // 非標(biāo)準(zhǔn) cancel 取消 bubble 泡泡}, false);var father = document.querySelector('.father');// 給father注冊(cè)單擊事件father.addEventListener('click', function() {alert('father');}, false);// 給document注冊(cè)單擊事件document.addEventListener('click', function() {alert('document');})</script>阻止事件冒泡的兼容性處理
1.3.8 事件委托
什么是事件委托
把事情委托給別人,代為處理。事件委托也稱為事件代理,在 jQuery 里面稱為事件委派。
說白了就是,不給子元素注冊(cè)事件,給父元素注冊(cè)事件,把處理代碼在父元素的事件中執(zhí)行。
舉例說明
快遞員手里有100個(gè)快遞,小區(qū)中有100個(gè)居民,挨個(gè)派送到家太麻煩了,速度也慢,居民等的也著急
處理方式:將100個(gè)快遞放到菜鳥驛站,100個(gè)居民去菜鳥驛站取貨,快遞省事,速度也快,居民也不用等待
本來送快遞是快遞員自己的事,結(jié)果把這個(gè)事情委派給了菜鳥驛站,這就是事件委派
js事件中的代理:
事件委托的原理
? 給父元素注冊(cè)事件,利用事件冒泡,當(dāng)子元素的事件觸發(fā),會(huì)冒泡到父元素,然后去控制相應(yīng)的子元素。
事件委托的作用
-
我們只操作了一次 DOM ,提高了程序的性能。
-
動(dòng)態(tài)新創(chuàng)建的子元素,也擁有事件。
1.4. 常用鼠標(biāo)事件
1.4.1 案例:禁止選中文字和禁止右鍵菜單
<body>我是一段不愿意分享的文字<script>// 1. contextmenu 我們可以禁用右鍵菜單document.addEventListener('contextmenu', function(e) {e.preventDefault();})// 2. 禁止選中文字 selectstartdocument.addEventListener('selectstart', function(e) {e.preventDefault();})</script> </body>1.4.2 鼠標(biāo)事件對(duì)象
1.4.3 獲取鼠標(biāo)在頁(yè)面的坐標(biāo)
<script>// 鼠標(biāo)事件對(duì)象 MouseEventdocument.addEventListener('click', function(e) {// 1. client 鼠標(biāo)在可視區(qū)的x和y坐標(biāo)console.log(e.clientX);console.log(e.clientY);console.log('---------------------');// 2. page 鼠標(biāo)在頁(yè)面文檔的x和y坐標(biāo)console.log(e.pageX);console.log(e.pageY);console.log('---------------------');// 3. screen 鼠標(biāo)在電腦屏幕的x和y坐標(biāo)console.log(e.screenX);console.log(e.screenY);})</script>1.4.4 案例:和魔鬼賽跑
<img src="images/devil.gif" alt=""><script>var img = document.querySelector('img');document.addEventListener('mousemove', function(e) {// 1. mousemove只要我們鼠標(biāo)移動(dòng)1px 就會(huì)觸發(fā)這個(gè)事件// 2.核心原理: 每次鼠標(biāo)移動(dòng),我們都會(huì)獲得最新的鼠標(biāo)坐標(biāo), // 把這個(gè)x和y坐標(biāo)做為圖片的top和left 值就可以移動(dòng)圖片var x = e.pageXvar y = e.pageYimg.style.left = x-img.width + 'px'img.style.top = y-img.height/2 + 'px'});</script>總結(jié)
以上是生活随笔為你收集整理的系统带你学习 WebAPIs 第三讲的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一理想ONE雨天路边起火:原因未明
- 下一篇: java信息管理系统总结_java实现科