--- tags: API,DOM,第三章 --- # 串接API之DOM第三章 ## DOM統整 創建 1.document.write 2.innerHTML 3.createElement 增 1.appendChild 2.insertBefore 刪 1.removeChild 改 1.修改元素屬性:src、href、title 2.修改普通元素內容:innerHTML、innerText 3.修改表單元素:value、type、disabled 4.修改元素樣式:style、className 查 1.DOM舊方法:getElementById、getElementsByTagName 2.H5新方法:querySelector、querySelectorAll 3.利用節點 父:parentNode 子:children 兄:previousElementSibling、nextElementSibling 屬性操作 1.setAttribute設置 2.getAttribute得到 3.removeAttribute移除 事件操作 | 鼠標事件 | 觸發條件 | | ----------- | ---------------- | | onclick | 滑鼠點擊左鍵觸發 | | onmouseover | 滑鼠經過觸發 | | onmouseout | 滑鼠離開觸發 | | onfocus | 獲得滑鼠焦點觸發 | | onblur | 失去滑鼠焦點觸發 | | onmousemove | 滑鼠移動觸發 | | onmouseup | 滑鼠彈起觸發 | | onmousedown | 滑鼠按下觸發 | ## 三種動態創建元素 ### document.write() 會導致頁面重繪 ``` <body> <button>點擊</button> <p>abc</p> <script> var btn = document.querySelector('button'); btn.onclick = function () { document.write('<div>123</div>'); }; </script> </body> ``` ### element.innerHTML 測速:約770毫秒 ``` <body> <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> </body> ``` 測速:約1毫秒 ``` <body> <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> </body> ``` ### document.createElement() 測速:約5毫秒 ```javascript= 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(); ``` ### 總結 ``` <body> <div class="inner"></div> <div class="create"></div> <script> var inner = document.querySelector('.inner'); for (i = 1; i <= 100; i++) { inner.innerHTML = '<a href="#">百度</a>'; } var create = document.querySelector('.create'); for (var i = 1; i <= 100; i++) { var a = document.createElement('a'); create.appendChild(a); } </script> </body> ``` ``` <body> <div class="inner"></div> <div class="create"></div> <script> var inner = document.querySelector('.inner'); var arr =[] for (i = 1; i <= 100; i++){ arr.push('<a href="#">百度</a>') } inner.innerHTML=arr.join(''); var create = document.querySelector('.create'); for (var i = 1; i <= 100; i++) { var a = document.createElement('a'); create.appendChild(a); } </script> </body> ``` ## 註冊事件2種方式 ### 傳統註冊 具有唯一性 ``` <body> <button onclick="alert('hi')">按我</button> </body> ``` ``` <body> <button onclick="alert('hi')">按我</button> <button>2號</button> <script> var btn = document.querySelectorAll('button'); btn[1].onclick = function () { alert('hello'); }; </script> </body> ``` ``` <body> <button onclick="alert('hi')">按我</button> <button>2號</button> <script> var btn = document.querySelectorAll('button'); btn[1].onclick = function () { alert('hello'); }; // 前面的被覆蓋了 btn[1].onclick = function () { alert('see'); }; </script> </body> ``` ### 方法監聽註冊 w3c標準 同元素同事件可以註冊多個監聽器 ``` eventTarget.addEventListener(type,listener[,useCapture]) ``` eventTarget目標對象 type事件類型字符串,比如click、mouseover,注意不要帶on listener事件處理函數 useCapture可選參數,是一個布林值(默認false) ``` <body> <button>安安</button> <script> var btn = document.querySelector('button'); btn.addEventListener('click', function () { alert('100'); }); btn.addEventListener('click', function () { alert('200'); }); </script> </body> ``` ### ie9舊方法(不要用) 非標準 ``` eventTarget.attachEvent(eventNameWithOn,callback) ``` eventNameWithOn事件類型字符串,比如onclick、onmouseover,注意有on callback事件處理函數 ``` <body> <button>安安</button> <script> var btn = document.querySelector('button'); btn.attachEvent('onclick', function () { alert('100'); }) </script> </body> ``` ## 刪除事件 傳統方法 ``` eventTarget.onclick = null; ``` 監聽註冊方法 ``` eventTarget.removeEventListener(type,listener[,useCapture]) ``` ``` <!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, initial-scale=1.0" /> <title>Document</title> <style> div { width: 100px; height: 100px; background-color: pink; } </style> </head> <body> <div>1</div> <div>2</div> <script> var divs = document.querySelectorAll('div'); divs[0].onclick = function () { alert(11); divs[0].onclick = null; }; divs[1].addEventListener('click', fn); // 裡面的fn不用加小括號調用 function fn() { alert(22); divs[1].removeEventListener('click', fn); } </script> </body> </html> ``` ## 事件流 ![](https://i.imgur.com/xclyFLz.jpg) ![](https://i.imgur.com/MeMIa5g.jpg) 1.JS單次只能執行捕獲或冒泡其中一階段 2.onclick和attachEvent只能得到冒泡階段 3.實際開發比較關注冒泡 4.有些事件沒有冒泡,如onblur、onfocus、onmouseenter、onmouseleave eventTarget.addEventListener(type,listener[,useCapture]) 第三個參數是true就在捕獲階段調用 第三個參數是false就在冒泡階段調用 ``` <!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, initial-scale=1.0" /> <title>Document</title> <style> .father { width: 800px; height: 800px; background-color: pink; } .son { width: 400px; height: 400px; background-color: green; } </style> </head> <body> <div class="father"> <div class="son">123</div> </div> <script> // 捕獲 var son = document.querySelector('.son'); son.addEventListener( 'click', function () { alert('son'); }, true ); var father = document.querySelector('.father'); father.addEventListener( 'click', function () { alert('father'); }, true ); // 冒泡 var son = document.querySelector('.son'); son.addEventListener( 'click', function () { alert('son'); }, false ); var father = document.querySelector('.father'); father.addEventListener( 'click', function () { alert('father'); }, false ); document.addEventListener('click', function () { alert('document'); }); </script> </body> </html> ``` ## 事件對象 1.event事件對象,寫到監聽函數小括號裡,當型參看 2.有了事件才有事件對象,是系統自動創建,我們不用傳遞參數 3.事件對象是事件的相關數據集合 4.事件對象可以自己命名,如event、evt、e ``` <body> <div>123</div> <script> var div = document.querySelector('div'); div.onclick = function (event) { console.log(event); }; div.addEventListener('click', function (e) { console.log(e); }); </script> </body> ``` ## 區別 e.target標準 e.srcElement非標準 e.currentTarget少用 ``` <body> <div>123</div> <ul> <li>abc</li> <li>abc</li> <li>abc</li> </ul> <script> var div = document.querySelector('div'); div.addEventListener('click', function (e) { console.log(e.target); console.log(this); }); var ul = document.querySelector('ul'); ul.addEventListener('click', function (e) { // e.target指向點擊的對象 console.log(e.target); // this指向綁定事件的對象 console.log(this); // e.currentTarget跟this很像 console.log(e.currentTarget); }); </script> </body> ``` ## 阻止默認行為 e.type返回事件的類型,如click、mouseover不帶on e.preventDefault()標準 e.returnValue非標準 ``` <body> <div>123</div> <a href="https://www.google.com/">google</a> <form action="https://www.google.com/"> <input type="submit" value="提交" name="sub" /> </form> <script> var div = document.querySelector('div'); div.addEventListener('click', fn); div.addEventListener('mouseover', fn); div.addEventListener('mouseout', fn); function fn(e) { console.log(e.type); } // 阻止默認 var a = document.querySelector('a'); a.addEventListener('click', function (e) { e.preventDefault(); }); // 傳統方法 a.onclick = function (e) { return false; alert(11); // 不執行 }; </script> </body> ``` ## 阻止冒泡 e.stopPropagation()標準 e.cancelBubble非標準 ``` <!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, initial-scale=1.0" /> <title>Document</title> <style> .father { width: 800px; height: 800px; background-color: pink; } .son { width: 400px; height: 400px; background-color: green; } </style> </head> <body> <div class="father"> <div class="son">123</div> </div> <script> // 捕獲 var son = document.querySelector('.son'); son.addEventListener( 'click', function () { alert('son'); }, true ); var father = document.querySelector('.father'); father.addEventListener( 'click', function () { alert('father'); }, true ); // 冒泡 var son = document.querySelector('.son'); son.addEventListener( 'click', function (e) { alert('son'); e.stopPropagation(); }, false ); var father = document.querySelector('.father'); father.addEventListener( 'click', function () { alert('father'); }, false ); document.addEventListener('click', function () { alert('document'); }); </script> </body> </html> ``` ## 冒泡簡單應用 ``` <body> <ul> <li>天線寶寶說你好</li> <li>天線寶寶說你好</li> <li>天線寶寶說你好</li> <li>天線寶寶說你好</li> <li>天線寶寶說你好</li> <li>天線寶寶說你好</li> </ul> <script> var ul = document.querySelector('ul'); ul.addEventListener('click', function (e) { alert('天線寶寶說你好'); e.target.style.backgroundColor = 'pink'; }); </script> </body> ``` ## 進階鼠標事件 ``` <body> 我是一段不願意被分享的文字 <script> // 1.禁止右鍵菜單 document.addEventListener('contextmenu', function (e) { e.preventDefault(); }); // 2.禁止滑鼠選中 document.addEventListener('selectstart', function (e) { e.preventDefault(); }); </script> </body> ``` ## 滑鼠座標 ``` <!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, initial-scale=1.0" /> <title>Document</title> <style> body { height: 3000px; } </style> </head> <body> <script> document.addEventListener('click', function (e) { // 1.可視區的x和y座標 console.log(e.clientX); console.log(e.clientY); console.log('----------'); // 2.頁面文檔的x和y座標 console.log(e.pageX); console.log(e.pageY); console.log('----------'); // 2.電腦螢幕的x和y座標 console.log(e.screenX); console.log(e.screenY); }); </script> </body> </html> ``` ## 案例:滑鼠天使 ``` <!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, initial-scale=1.0" /> <title>Document</title> <style> img { position: absolute; cursor: none; } </style> </head> <body> <img src="greenman.gif" alt="" /> <script> var pic = document.querySelector('img'); document.addEventListener('mousemove', function (e) { var x = e.pageX; var y = e.pageY; pic.style.left = x - 10 + 'px'; pic.style.top = y - 10 + 'px'; }); </script> </body> </html> ``` ## 鍵盤事件 (優先順序3)onkeyup (優先順序1)onkeydown (優先順序2)onkeypress(不識別功能鍵ctrl shift 箭頭) ``` <body> <script> document.onkeyup = function () { console.log('我彈起了'); }; document.addEventListener('keyup', function () { console.log('彈'); }); document.addEventListener('keydown', function () { console.log('按down'); }); document.addEventListener('keypress', function () { console.log('按press'); }); </script> </body> ``` ## keyCode 查ASCII碼 http://c.biancheng.net/c/ascii/ onkeyup不區分英文大小寫 onkeydown不區分英文大小寫 onkeypress區分英文大小寫 ``` <body> <script> document.addEventListener('keyup', function (e) { console.log(e); console.log(e.keyCode); }); document.addEventListener('keydown', function (e) { console.log('down' + e.keyCode); }); document.addEventListener('keypress', function (e) { console.log('press' + e.keyCode); }); </script> </body> ``` ## 模擬京東搜尋 focus()獲得焦點 ``` <body> <input type="text" /> <script> var search = document.querySelector('input'); document.addEventListener('keyup', function (e) { if (e.keyCode === 83) { search.focus(); } }); </script> </body> ``` ## 快遞單號放大鏡 ``` <!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, initial-scale=1.0" /> <title>Document</title> <style> * { margin: 0; padding: 0; } .search { position: relative; width: 178px; margin: 100px; } .con { display: none; position: absolute; top: -40px; width: 171px; border: 1px solid rgba(0, 0, 0, 0.2); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); padding: 5px 0; font-size: 18px; line-height: 20px; color: #333; } .con::before { content: ''; width: 0; height: 0; position: absolute; top: 28px; left: 18px; border: 8px solid #000; border-style: solid dashed dashed; border-color: #fff transparent transparent; } </style> </head> <body> <div class="search"> <div class="con">123</div> <input type="text" placeholder="快遞單號" class="jd" /> </div> <script> var con = document.querySelector('.con'); var jd_input = document.querySelector('.jd'); jd_input.addEventListener('keyup', function () { if (this.value == '') { con.style.display = 'none'; } else { con.style.display = 'block'; con.innerText = this.value; } }); jd_input.addEventListener('blur', function () { con.style.display = 'none'; }); jd_input.addEventListener('focus', function () { if (this.value !== '') { con.style.display = 'block'; } }); </script> </body> </html> ```