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