事件
1 事件流
-
冒泡:從該元素開始由里向外觸發(fā)一類事件揉忘,事件對(duì)象中的事件源為該元素,觸發(fā)同一類事件翅楼,在子級(jí)父級(jí)祖級(jí)中拿到的事件源一樣乎赴,均為被觸發(fā)元素忍法;
- 阻止冒泡:
e.stopPropagation?e.stopPropagation():e.cancelBubble=true;
- 關(guān)于冒泡的運(yùn)用:典型的是事件委托
- 事件委托:將事件添加到最高級(jí)元素上,事件中獲取事件源的屬性榕吼,當(dāng)觸發(fā)某元素上的事件時(shí)饿序,就會(huì)在最高級(jí)中獲取事件源,也就是該元素羹蚣;
- 實(shí)例1:在多層嵌套的div中原探,點(diǎn)擊哪個(gè)元素,就彈出哪個(gè)元素的class名顽素;
- 方法:
- 1)遍歷div咽弦,給每個(gè)元素添加點(diǎn)擊事件,然后彈出class名戈抄,但是會(huì)出現(xiàn)冒泡事件,所以必須阻止冒泡事件
- 2)事件委托
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>冒泡與阻止冒泡</title> <style> div{ padding: 100px; font-size: 50px; } .div1{ background-color: red; } .div2{ background-color: blue; } .div3{ background-color: green; } </style> </head> <body> <div class="div1">div1 <div class="div2">div2 <div class="div3">div3</div> </div> </div> <script> //需求:點(diǎn)擊誰后专,彈出誰的class名 var oDiv1=document.getElementsByTagName("div")[0]; var aDiv=document.getElementsByTagName("div"); //第一種方法:遍歷div划鸽,給每個(gè)元素添加點(diǎn)擊事件,然后彈出class名戚哎,要阻止冒泡事件 for(var i=0; i<aDiv.length; i++){ aDiv[i].onclick=function (e) { alert(this.className); //會(huì)存在冒泡事件裸诽,所以要阻止冒泡 e.stopPropagation? e.stopPropagation():e.cancelBubble=true; } } //第二種方法:事件委托,委托給最高級(jí)型凳,通過事件源獲取 //由于事件存在冒泡特性丈冬,所以在觸發(fā)某元素的事件時(shí),同時(shí)會(huì)觸發(fā)其父級(jí)和祖級(jí)的該類事件甘畅,都傳入同一個(gè)事件對(duì)象埂蕊,里面的事件源都是觸發(fā)的某元素,所以只要在最高級(jí)上添加點(diǎn)擊事件疏唾,里面獲取事件源的class名即可 oDiv1.onclick=function (e) { e=e||window.event; e.target=e.target||e.srcElement; alert(e.target.className); } </script> </body> </html>
- 方法:
- 實(shí)例2:在body元素中有多個(gè)div元素蓄氧,在點(diǎn)擊里面的a鏈接后,就刪除該a元素的父級(jí)div槐脏;
- 方法:事件委托給最高級(jí)body元素喉童,給body添加點(diǎn)擊事件,然后在事件匿名函數(shù)中獲取事件源顿天,然后刪除事件源的父級(jí)div;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件委托</title> <style> div{ width: 100px; height: 100px; background-color: lightseagreen; float: left; margin: 5px; } div a{ color: red; text-decoration: none; font-weight: bold; } </style> </head> <body> <!--<div> <a href="javascript:void(0);">點(diǎn)吧</a> </div>--> <script> for(var i=0; i<20; i++){ var odiv=document.createElement("div"); odiv.innerHTML=`<a href="javascript:void(0);">${i}點(diǎn)吧</a>`; document.body.appendChild(odiv); } //事件委托堂氯,給最高級(jí)元素添加事件 //當(dāng)點(diǎn)擊a標(biāo)簽時(shí)蔑担,就會(huì)觸發(fā)a的點(diǎn)擊事件,同時(shí)由里向外觸發(fā)父級(jí)div和祖級(jí)body的點(diǎn)擊事件咽白,然后每個(gè)事件中拿到的事件對(duì)象上的target屬性值都是a元素啤握,即事件源都是a元素; //通過判斷事件源來決定刪除哪個(gè)a元素的父級(jí)局扶; document.body.onclick=function (e) { e=e||window.event; e.target=e.target || e.srcElement; if(e.target.tagName.toLowerCase()==="a"){ this.removeChild(e.target.parentNode); } } </script> </body> </html>
- 注:某個(gè)元素事件發(fā)生恨统,不用給其添加代碼,只要在它身上觸發(fā)該事件就行三妈,添加代碼畜埋,只不過給其設(shè)置一個(gè)能夠顯現(xiàn)出來的動(dòng)作而已,不添加畴蒲,也會(huì)觸發(fā)悠鞍;
- 阻止冒泡:
-
onmouseenter、onmouseleave模燥、onmouseover咖祭、onmouseout四者關(guān)系解讀
- 相同點(diǎn):都是添加鼠標(biāo)移入移出事件
- 不同點(diǎn):onmouseover和onmouseout中會(huì)存在冒泡事件;onmouseenter和onmouseleave中不存在冒泡事件蔫骂;
- 實(shí)例解讀:
- 需求:當(dāng)鼠標(biāo)移動(dòng)到div元素身上時(shí)么翰,p元素顯示,顯示的時(shí)候辽旋,移動(dòng)到p元素身上浩嫌,仍然顯示,移動(dòng)到div和p元素之外的位置补胚,p元素再隱藏码耐;
- 方法:
- 使用onmouseenter與onmouseleave設(shè)置:當(dāng)光標(biāo)從div上移出到p元素上時(shí),沒有打印out,也沒有再次打印in,意思是兩個(gè)事件都沒有被觸發(fā)溶其,指的就是當(dāng)移動(dòng)到子級(jí)身上時(shí)骚腥,根本不算移出;所以給oDiv元素添加onmouseenter事件瓶逃,指的是當(dāng)光標(biāo)移入到它或者是它的子級(jí)束铭,都會(huì)觸發(fā)事件;不是冒泡事件厢绝,而是將oDiv和它的子級(jí)作為了一個(gè)整體纯露;
- 使用onmouseover與onmouseout設(shè)置:使用onmouseover和onmouseout也會(huì)實(shí)現(xiàn)需求,但是實(shí)現(xiàn)的過程不同代芜,當(dāng)光標(biāo)移入div會(huì)觸發(fā)onmouseover事件埠褪,然后打印in,當(dāng)光標(biāo)從div元素上移出并立刻進(jìn)入p元素時(shí),此時(shí)發(fā)生了兩個(gè)過程钞速,移出div時(shí)贷掖,會(huì)觸發(fā)div的onmouseout事件,打印out渴语,并使p隱藏苹威;然后迅速進(jìn)入p元素,此時(shí)觸發(fā)p元素的onmouseover事件驾凶,但是沒有動(dòng)作牙甫,會(huì)通過冒泡事件,連帶父級(jí)div觸發(fā)onmouseover事件调违,所以再次打印in,然后p顯示窟哺;所以肉眼沒有發(fā)現(xiàn)p被隱藏,又被顯示技肩。當(dāng)移出p元素時(shí)也是通過冒泡事件且轨,將父級(jí)onmouseout事件觸發(fā),進(jìn)而打印out虚婿,使p隱藏旋奢;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onmouseenter與onmouseleave解讀</title> <style> *{ margin: 0; padding: 0; } .div1{ width: 200px; height: 50px; background-color: lightseagreen; position: relative; margin: 20px auto; } .div1 p{ width: 500px; height: 300px; position: absolute; right: 0; top: 50px; background-color: lightpink; display: none; } </style> </head> <body> <div class="div1"> <p></p> </div> <script> //需求:當(dāng)鼠標(biāo)移動(dòng)到div元素身上時(shí),p元素顯示然痊,顯示的時(shí)候至朗,移動(dòng)到p元素身上,仍然顯示剧浸,移動(dòng)到div和p元素之外的位置锹引,p元素再隱藏; var oDiv=document.getElementsByTagName("div")[0]; var oP=document.getElementsByTagName("p")[0]; //1 使用onmouseenter與onmouseleave設(shè)置 oDiv.onmouseenter=function () { console.log("in"); oP.style.display="block"; }; oDiv.onmouseleave=function () { console.log("out"); oP.style.display="none"; }; //當(dāng)光標(biāo)移入div辛蚊,再移入p粤蝎,再移出p真仲,整個(gè)過程中打印結(jié)果:in-out袋马; //2 使用onmouseover與onmouseout設(shè)置 oDiv.onmouseover=function () { console.log("in"); oP.style.display="block"; }; oDiv.onmouseout=function () { console.log("out"); oP.style.display="none"; } //當(dāng)光標(biāo)移入div,再移入p秸应,再移出p虑凛,整個(gè)過程中打印結(jié)果:in-out-in-out </script> </body> </html>
-
冒泡的問題:給父級(jí)添加事件后,在子級(jí)上觸發(fā)软啼,還會(huì)觸發(fā)父級(jí)的事件桑谍,會(huì)重復(fù)觸發(fā),造成性能不好祸挪,還會(huì)造成代碼混亂锣披;
- 解決方法:在子級(jí)中添加相同事件,并在事件中阻止冒泡;代碼:
e.stopPropagation?e.stopPropagation():e.cancelBubble=true;
雹仿; - 通過關(guān)聯(lián)元素獲取到子級(jí)增热,然后判斷阻止,此方法只能解決代碼混亂問題胧辽,不會(huì)進(jìn)行性能優(yōu)化峻仇,父級(jí)事件還會(huì)因子級(jí)事件觸發(fā)而觸發(fā),只不過是在父級(jí)事件中阻斷了一些代碼的執(zhí)行邑商,避免重復(fù)設(shè)置摄咆,造成混亂;
- 在父級(jí)事件函數(shù)中人断,通過事件對(duì)象獲取事件源吭从,通過事件源來篩選觸發(fā)元素,不能阻止冒泡事件發(fā)生含鳞,但是可以阻止影锈,當(dāng)從子級(jí)觸發(fā)時(shí),不會(huì)再執(zhí)行父級(jí)函數(shù)體內(nèi)的代碼蝉绷;
- 解決方法:在子級(jí)中添加相同事件,并在事件中阻止冒泡;代碼:
-
冒泡的問題及解決問題的實(shí)例:
- 實(shí)例1:當(dāng)鼠標(biāo)滑到div上時(shí)鸭廷,新建一個(gè)p元素,讓其跟隨光標(biāo)移動(dòng)熔吗,當(dāng)光標(biāo)移出div后辆床,p元素消失;
- 問題:當(dāng)鼠標(biāo)移動(dòng)到子級(jí)p身上的時(shí)候桅狠,會(huì)觸發(fā)鼠標(biāo)事件讼载,通過冒泡觸發(fā)父級(jí)身上的鼠標(biāo)事件,進(jìn)而再新建一個(gè)p元素中跌,進(jìn)而出錯(cuò)咨堤;
- 解決方法:1)將子級(jí)p元素中的冒泡事件阻止,這樣父級(jí)就不會(huì)被關(guān)聯(lián)觸發(fā)漩符;2)利用對(duì)象事件上的屬性獲取添加事件元素的關(guān)聯(lián)元素博烂,判斷當(dāng)包含時(shí)号杠,則阻止程序執(zhí)行渊鞋,進(jìn)而不會(huì)被影響孵淘;3)利用onmouseenter和onmouseleave添加事件;
- 注意:鼠標(biāo)移動(dòng)事件太靈敏闷沥,所以需要在定位數(shù)值設(shè)置時(shí)使光標(biāo)與定位元素有一段距離萎战;
- 代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>實(shí)例2</title> <style> *{ margin: 0; padding: 0; } .div{ width: 500px; height: 350px; background-color: red; margin: 20px auto; position: relative; } .div p{ width: 50px; height: 50px; background-color: blue; position: absolute; } </style> </head> <body> <div class="div"></div> <script> var oDiv=document.getElementsByTagName("div")[0]; var oS=null; //方法1:將子級(jí)p元素中的冒泡事件阻止,這樣父級(jí)就不會(huì)被關(guān)聯(lián)觸發(fā)舆逃; oDiv.onmouseover=function () { oS=document.createElement("p"); oS.onmouseover=function (e) { //阻止冒泡事件 e=e||window.event; e.stopPropagation? e.stopPropagation():e.cancelBubble=true; }; this.appendChild(oS); }; oDiv.onmousemove=function (e) { e=e||window.event; oS.style.left=e.clientX-this.offsetLeft-this.clientLeft+5+"px"; oS.style.top=e.clientY-this.offsetTop-this.clientTop+5+"px"; }; oDiv.onmouseout=function () { oS.onmouseout=function (e) { //阻止冒泡事件 e=e||window.event; e.stopPropagation? e.stopPropagation():e.cancelBubble=true; }; this.removeChild(oS); } //方法2:利用對(duì)象事件上的屬性獲取添加事件元素的關(guān)聯(lián)元素蚂维,判斷當(dāng)包含時(shí)戳粒,則阻止程序執(zhí)行,進(jìn)而不會(huì)被影響虫啥; oDiv.onmouseover=function (e) { e=e||window.event; //關(guān)聯(lián)元素的獲取享郊,在事件對(duì)象上 var oMo=e.fromElement || e.realtedTarget; //判斷是否包含關(guān)聯(lián)元素,包含則阻止程序執(zhí)行孝鹊; if(this.contains(oMo)) return; oS=document.createElement("p"); this.appendChild(oS); }; oDiv.onmousemove=function (e) { e=e||window.event; oS.style.left=e.clientX-this.offsetLeft-this.clientLeft+8+"px"; oS.style.top=e.clientY-this.offsetTop-this.clientTop+8+"px"; }; oDiv.onmouseout=function (e) { e=e||window.event; var oMo=e.toElement || e.realtedTarget; if(this.contains(oMo)) return; this.removeChild(oS); } //方法3:使用onmouseenter和onmouseleave oDiv.onmouseenter=function () { oS=document.createElement("p"); this.appendChild(oS); }; oDiv.onmousemove=function (e) { e=e||window.event; oS.style.left=e.clientX-this.offsetLeft-this.clientLeft+10+"px"; oS.style.top=e.clientY-this.offsetTop-this.clientTop+10+"px"; }; oDiv.onmouseleave=function () { this.removeChild(oS); } </script> </body> </html>
- 實(shí)例2:當(dāng)鼠標(biāo)移動(dòng)到div元素身上時(shí)炊琉,p元素顯示,顯示的時(shí)候又活,移動(dòng)到p元素身上苔咪,仍然顯示,移動(dòng)到div和p元素之外的位置柳骄,p元素再隱藏团赏;
- 問題:當(dāng)鼠標(biāo)移動(dòng)到子級(jí)p元素身上時(shí),會(huì)觸發(fā)p元素的鼠標(biāo)事件耐薯,進(jìn)而再次觸發(fā)父級(jí)div的鼠標(biāo)事件舔清,這樣就會(huì)重復(fù)觸發(fā),性能不好曲初,所以要阻止子級(jí)的冒泡事件
- 解決方法:1)在子級(jí)中阻止冒泡事件体谒,但是需要在子級(jí)中添加顯示隱藏;2)通過對(duì)象事件獲取關(guān)聯(lián)元素臼婆;3)設(shè)置onmouseenter和onmouseleave事件抒痒,能夠解決性能問題,事件只觸發(fā)一次
- 注意:關(guān)聯(lián)元素的方法可取颁褂,但是沒有解決性能問題故响,因?yàn)榛阶蛹?jí)上,還是會(huì)觸發(fā)父級(jí)的鼠標(biāo)事件颁独,沒有完成性能優(yōu)化彩届,此處要注意的是,顯示隱藏代碼一定要設(shè)置在判斷元素之后誓酒;在父級(jí)事件中代碼執(zhí)行前樟蠕,判斷關(guān)聯(lián)元素的目的:是阻止父級(jí)事件中代碼的執(zhí)行,不會(huì)阻止冒泡事件的發(fā)生丰捷;
- 代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>冒泡問題解讀</title> <style> *{ margin: 0; padding: 0; } .div1{ width: 200px; height: 50px; background-color: lightseagreen; position: relative; margin: 20px auto; } .div1 p{ width: 500px; height: 300px; position: absolute; right: 0; top: 50px; background-color: lightpink; display: none; } </style> </head> <body> <div class="div1"> <p></p> </div> <script> //需求:當(dāng)鼠標(biāo)移動(dòng)到div元素身上時(shí)坯墨,p元素顯示寂汇,顯示的時(shí)候病往,移動(dòng)到p元素身上,仍然顯示骄瓣,移動(dòng)到div和p元素之外的位置停巷,p元素再隱藏; //問題:當(dāng)鼠標(biāo)移動(dòng)到子級(jí)p元素身上時(shí),會(huì)觸發(fā)p元素的鼠標(biāo)事件畔勤,進(jìn)而再次觸發(fā)父級(jí)div的鼠標(biāo)事件蕾各,這樣就會(huì)重復(fù)觸發(fā),性能不好庆揪,所以要阻止子級(jí)的冒泡事件 var oDiv=document.getElementsByTagName("div")[0]; var oP=document.getElementsByTagName("p")[0]; //方法1:在子級(jí)中阻止冒泡事件式曲,但是需要在子級(jí)中添加顯示隱藏; oDiv.onmouseover=function () { console.log("in"); oP.style.display="block"; oP.onmouseover=function (e) { //阻止冒泡但是要重新設(shè)置顯示隱藏缸榛; this.style.display="block"; e=e||window.event; //阻止子級(jí)的冒泡事件 e.stopPropagation?e.stopPropagation():e.cancelBubble=true; } }; oDiv.onmouseout=function () { console.log("out"); oP.style.display="none"; oP.onmouseout=function (e) { this.style.display="none"; e=e||window.event; e.stopPropagation?e.stopPropagation():e.cancelBubble=true; } } //方法2:通過對(duì)象事件獲取關(guān)聯(lián)元素 //方法可取但是沒有解決性能問題吝羞,因?yàn)榛阶蛹?jí)上,還是會(huì)觸發(fā)父級(jí)的鼠標(biāo)事件内颗,沒有完成性能優(yōu)化钧排,此處要注意的是,顯示隱藏代碼一定要設(shè)置在判斷元素之后 //在父級(jí)事件中代碼執(zhí)行前均澳,判斷關(guān)聯(lián)元素的目的:是阻止父級(jí)事件中代碼的執(zhí)行恨溜,不會(huì)阻止冒泡事件的發(fā)生; oDiv.onmouseover=function (e) { console.log("in"); e= e||window.event; var oMo=e.fromElement || e.relatedTarget; if(this.contains(oMo)) return; console.log(2); oP.style.display="block"; }; oDiv.onmouseout=function (e) { console.log("out"); e= e||window.event; var oMo=e.toElement || e.relatedTarget; if(this.contains(oMo)) return; console.log(1); oP.style.display="none"; } //打印結(jié)果:從進(jìn)入div,在出來進(jìn)入p找前,然后再從p移出這個(gè)過程的打印結(jié)果為:in-2-out-in-out-1; //方法3:設(shè)置onmouseenter和onmouseleave事件糟袁,能夠解決性能問題,事件只觸發(fā)一次 oDiv.onmouseenter=function () { console.log("in"); oP.style.display="block"; }; oDiv.onmouseleave=function () { console.log("out"); oP.style.display="none"; } </script> </body> </html>
- 實(shí)例3:當(dāng)鼠標(biāo)移上div元素身上時(shí)躺盛,p顯示系吭;移出div元素后,p隱藏颗品;強(qiáng)調(diào):移出到任何位置肯尺,p都隱藏,移動(dòng)p元素身上躯枢,也必須隱藏则吟;
- 問題:當(dāng)鼠標(biāo)移動(dòng)到子級(jí)p元素身上時(shí),會(huì)觸發(fā)p元素的鼠標(biāo)事件锄蹂,進(jìn)而再次觸發(fā)父級(jí)div的鼠標(biāo)事件氓仲,這樣就會(huì)重復(fù)觸發(fā),性能不好得糜,同時(shí)當(dāng)鼠標(biāo)移動(dòng)到子級(jí)p元素身上的時(shí)候敬扛,子級(jí)不會(huì)隱藏,所以要阻止子級(jí)的冒泡事件朝抖;
- 解決方法:1)在子級(jí)元素身上綁定同行為事件啥箭,然后在事件函數(shù)中阻止冒泡發(fā)生;2)在父級(jí)元素中治宣,通過事件對(duì)象獲取事件源急侥,然后判斷事件源的nodeName來獲取元素TagName名砌滞,判斷是否為父級(jí)元素標(biāo)簽,若不是坏怪,則阻止代碼執(zhí)行贝润;
- 代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>需求2</title> <style> *{ margin: 0; padding: 0; } .div1{ width: 200px; height: 50px; background-color: lightseagreen; position: relative; margin: 20px auto; } .div1 p{ width: 500px; height: 300px; position: absolute; right: 0; top: 50px; background-color: lightpink; display: none; } </style> </head> <body> <div class="div1"> <p></p> </div> <script> var oDiv=document.getElementsByTagName("div")[0]; var oP=document.getElementsByTagName("p")[0]; //方法1:在子級(jí)事件函數(shù)中阻止冒泡發(fā)生; oDiv.onmouseover=function () { console.log("in"); oP.style.display="block"; oP.onmouseover=function (e) { e=e||window.event; //阻止子級(jí)的冒泡事件 e.stopPropagation?e.stopPropagation():e.cancelBubble=true; } }; oDiv.onmouseout=function () { console.log("out"); oP.style.display="none"; oP.onmouseout=function (e) { e=e||window.event; e.stopPropagation?e.stopPropagation():e.cancelBubble=true; } }铝宵; //方法2:在父級(jí)元素中判斷事件源 oDiv.onmouseover=function(e){ e=e || window; e.target=e.target || e.srcElement; if(e.target.nodeName.toLowerCase!=="div") return; oP.style.display="block"; }; oDiv.onmouseout=function(e){ e=e || window; e.target=e.target || e.srcElement; if(e.target.nodeName.toLowerCase!=="div") return; oP.style.display="none"; }; </script> </body> </html>
- 實(shí)例1:當(dāng)鼠標(biāo)滑到div上時(shí)鸭廷,新建一個(gè)p元素,讓其跟隨光標(biāo)移動(dòng)熔吗,當(dāng)光標(biāo)移出div后辆床,p元素消失;
-
購物車點(diǎn)擊版實(shí)例
- 需求:當(dāng)點(diǎn)擊div元素及p元素時(shí)打掘,p元素顯示,點(diǎn)擊除二者以外的任何區(qū)域都讓p隱藏
- 思路:如果一個(gè)父級(jí)容器下添加多個(gè)事件鹏秋,那么就將事件委托給父級(jí)容器胧卤,通過判斷事件源來進(jìn)行相應(yīng)的操作;
- 方法:1)通過開關(guān)思想拼岳,控制隱藏與顯示枝誊,但是會(huì)存在一個(gè)問題,在第二個(gè)判斷中如果不設(shè)置bOk=true惜纸,就會(huì)出現(xiàn)叶撒,第一次點(diǎn)擊div后,p顯示耐版,然后點(diǎn)擊外面祠够,p消失,但此時(shí)的bOk為false,再次點(diǎn)擊div時(shí)粪牲,會(huì)走else語句古瓤,不會(huì)顯示;所以必須設(shè)置bOk=true; 2)通過判斷p的行間樣式是否為block來控制顯示和隱藏腺阳;3)通過給父級(jí)容器添加點(diǎn)擊事件落君,然后通過事件對(duì)象來獲取事件源,判斷事件源的nodeName是否為div和p的tagName名亭引,若是二者之一绎速,則設(shè)置p為顯示,若都不是焙蚓,則設(shè)置p為隱藏纹冤;
- 知識(shí)點(diǎn):事件委托的應(yīng)用環(huán)境及行間樣式的獲取
- 代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>購物車點(diǎn)擊版實(shí)例</title> <style> *{ margin: 0; padding: 0; } html,body{ height: 100%; } .div1{ width: 200px; height: 50px; background-color: lightseagreen; position: relative; margin: 20px auto; } .div1 p{ width: 500px; height: 300px; position: absolute; right: 0; top: 50px; background-color: lightpink; display: none; } </style> </head> <body> <div class="div1"> <p></p> </div> <script> //需求:當(dāng)點(diǎn)擊div元素及p元素時(shí),p元素顯示购公,點(diǎn)擊除二者以外的任何區(qū)域都讓p隱藏 var oDiv=document.getElementsByTagName("div")[0]; var oP=document.getElementsByTagName("p")[0]; var bOk=true; //思路:如果一個(gè)父級(jí)容器下添加多個(gè)事件萌京,那么就將事件委托給父級(jí)容器,通過判斷事件源來進(jìn)行相應(yīng)的操作宏浩; //方法1:通過開關(guān)思想知残,控制隱藏與顯示,但是會(huì)存在一個(gè)問題绘闷,在第二個(gè)判斷中如果不設(shè)置bOk=true橡庞,就會(huì)出現(xiàn),第一次點(diǎn)擊div后印蔗,p顯示扒最,然后點(diǎn)擊外面,p消失华嘹,但此時(shí)的bOk為false,再次點(diǎn)擊div時(shí)吧趣,會(huì)走else語句,不會(huì)顯示耙厚;所以必須天機(jī)bOk=true; document.body.onclick=function (e) { e=e||window; var target=e.target ||e.srcElement; if(target.className.toLowerCase()==="div1"){ if(bOk){ oP.style.display="block"; }else{ oP.style.display="none"; } bOk=!bOk; }else if(target.tagName.toLowerCase()!=="p"){ oP.style.display="none"; bOk=true; } }; //方法2:通過判斷p的行間樣式是否為block來控制顯示和隱藏 //需注意:在第一次點(diǎn)擊div時(shí)强挫,此時(shí)oP.style.display拿到的值為空,因?yàn)槟玫降氖切虚g樣式薛躬,行間沒有設(shè)置俯渤,而在style中設(shè)置的都是非行間樣式,通過style是不能獲取的型宝,所以第一次點(diǎn)擊會(huì)執(zhí)行else語句八匠; document.body.onclick=function (e) { e=e||window; var target=e.target ||e.srcElement; if(target.className.toLowerCase()==="div1"){ if(oP.style.display==="block"){ oP.style.display="none"; }else{ oP.style.display="block"; } }else if(target.tagName.toLowerCase()!=="p"){ oP.style.display="none"; } } //方法3:通過判斷事件源的nodeName來進(jìn)行設(shè)置 document.body.onclick=function (e) { e=e || window.event; e.target=e.target || e.srcElement; if(e.target.nodeName==="DIV" || e.target.nodeName==="P"){ oP.style.display="block"; }else{ oP.style.display="none"; } } </script> </body> </html>
-
購物車點(diǎn)擊版實(shí)例2
- 需求:當(dāng)點(diǎn)擊div時(shí),p顯示趴酣,當(dāng)移出div后梨树,p隱藏,但是保證從div移出到p元素身上時(shí)岖寞,p不隱藏抡四,從p上移出后,p隱藏仗谆;
- 方法:1)用onclick和onmouseleave事件設(shè)置指巡;2)用onclick和onmouseout事件設(shè)置,但是用onmouseout事件設(shè)置隶垮,會(huì)存在問題:當(dāng)移出div到p元素身上后厌处,p會(huì)隱藏;所以需要獲取關(guān)聯(lián)元素岁疼,阻斷隱藏代碼阔涉;
- 知識(shí)點(diǎn):onmouseout與onmouseleave的區(qū)別,以及關(guān)聯(lián)元素的獲取及阻斷代碼執(zhí)行捷绒;
- 代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>購物車實(shí)例</title> <style> *{ margin: 0; padding: 0; } .div1{ width: 200px; height: 50px; background-color: lightseagreen; position: relative; margin: 20px auto; } .div1 p{ width: 500px; height: 300px; position: absolute; right: 0; top: 50px; background-color: lightpink; display: none; } </style> </head> <body> <div class="div1"> <p></p> </div> <script> //需求:當(dāng)點(diǎn)div時(shí)瑰排,p顯示,當(dāng)移出div后暖侨,p隱藏椭住,但是保證從div移出到p元素身上時(shí),p不隱藏字逗,從p上移出后京郑,p隱藏宅广; //方法1:用點(diǎn)擊事件和onmouseleave事件設(shè)置 var oDiv=document.getElementsByTagName("div")[0]; var oP=document.getElementsByTagName("p")[0]; oDiv.onclick=function () { oP.style.display="block"; }; //用onmouseleave設(shè)置,當(dāng)移出div到p元素身上后些举,p不會(huì)隱藏跟狱; oDiv.onmouseleave=function () { oP.style.display="none"; }; //方法2:用onclick和onmouseout事件設(shè)置,但是用onmouseout事件設(shè)置户魏,會(huì)存在問題:當(dāng)移出div到p元素身上后驶臊,p會(huì)隱藏;所以需要獲取關(guān)聯(lián)元素叼丑,阻斷隱藏代碼关翎; oDiv.onclick=function () { oP.style.display="block"; }; oDiv.onmouseout=function (e) { e=e||window.event; //獲取關(guān)聯(lián)元素,阻斷隱藏代碼執(zhí)行鸠信; var omo=e.toElement || e.relatedTarget; if(this.contains(omo)) return; oP.style.display="none"; } </script> </body> </html>
知識(shí)點(diǎn)擴(kuò)充
- 定位:
- 頁面結(jié)構(gòu)中元素A包含著B元素纵寝,A為父級(jí)元素,B為子級(jí)元素星立,B相對(duì)于A定位
- B的盒子模型是包含margin在內(nèi)的大盒子店雅,然后相對(duì)于A的邊框內(nèi)邊緣定位,即若B的margin設(shè)置為0贞铣,并且定位中l(wèi)eft也設(shè)置為0闹啦,則B的左邊框外邊緣與A的左邊框內(nèi)邊緣貼合,當(dāng)添加margin之后辕坝,二者之間會(huì)存在相應(yīng)間隔窍奋;
- 總結(jié):子級(jí)元素盒子模型(包含margin)相對(duì)于定位父級(jí)的邊框內(nèi)邊緣進(jìn)行定位;