整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          JavaScript 的這個難點,毀掉了多少程序員

          JavaScript 的這個難點,毀掉了多少程序員

          . this 適合你嗎?

          我看到許多文章在介紹 JavaScript 的 this 時都會假設(shè)你學(xué)過某種面向?qū)ο蟮木幊陶Z言,比如 Java、C++ 或 Python 等。但這篇文章面向的讀者是那些不知道 this 是什么的人。我盡量不用任何術(shù)語來解釋 this 是什么,以及 this 的用法。

          也許你一直不敢解開 this 的秘密,因為它看起來挺奇怪也挺嚇人的。或許你只在 StackOverflow 說你需要用它的時候(比如在 React 里實現(xiàn)某個功能)才會使用。

          在深入介紹 this 之前,我們首先需要理解函數(shù)式編程和面向?qū)ο缶幊讨g的區(qū)別。

          2. 函數(shù)式編程 vs 面向?qū)ο缶幊?/strong>

          你可能不知道,JavaScript 同時擁有面向?qū)ο蠛秃瘮?shù)式的結(jié)構(gòu),所以你可以自己選擇用哪種風(fēng)格,或者兩者都用。

          我在很早以前使用 JavaScript 時就喜歡函數(shù)式編程,而且會像躲避瘟疫一樣避開面向?qū)ο缶幊蹋驗槲也焕斫饷嫦驅(qū)ο笾械年P(guān)鍵字,比如 this。我不知道為什么要用 this。似乎沒有它我也可以做好所有的工作。

          而且我是對的。

          在某種意義上 。也許你可以只專注于一種結(jié)構(gòu)并且完全忽略另一種,但這樣你只能是一個 JavaScript 開發(fā)者。為了解釋函數(shù)式和面向?qū)ο笾g的區(qū)別,下面我們通過一個數(shù)組來舉例說明,數(shù)組的內(nèi)容是 Facebook 的好友列表。

          假設(shè)你要做一個 Web 應(yīng)用,當(dāng)用戶使用 Facebook 登錄你的 Web 應(yīng)用時,需要顯示他們的 Facebook 的好友信息。你需要訪問 Facebook 并獲得用戶的好友數(shù)據(jù)。這些數(shù)據(jù)可能是 firstName、lastName、username、numFriends、friendData、birthday 和 lastTenPosts 等信息。

          const data=[
           {
           firstName: 'Bob',
           lastName: 'Ross',
           username: 'bob.ross', 
           numFriends: 125,
           birthday: '2/23/1985',
           lastTenPosts: ['What a nice day', 'I love Kanye West', ...],
           },
           ...
          ]
          

          假設(shè)上述數(shù)據(jù)是你通過 Facebook API 獲得的。現(xiàn)在需要將其轉(zhuǎn)換成方便你的項目使用的格式。我們假設(shè)你想顯示的好友信息如下:

          • 姓名,格式為`${firstName} ${lastName}`
          • 三篇隨機文章
          • 距離生日的天數(shù)


          3. 函數(shù)式方式

          函數(shù)式的方式就是將整個數(shù)組或者數(shù)組中的某個元素傳遞給某個函數(shù),然后返回你需要的信息:

          const fullNames=getFullNames(data)
          // ['Ross, Bob', 'Smith, Joanna', ...]
          

          首先我們有 Facebook API 返回的原始數(shù)據(jù)。為了將其轉(zhuǎn)換成需要的格式,首先要將數(shù)據(jù)傳遞給一個函數(shù),函數(shù)的輸出是(或者包含)經(jīng)過修改的數(shù)據(jù),這些數(shù)據(jù)可以在應(yīng)用中向用戶展示。

          我們可以用類似的方法獲得隨機三篇文章,并且計算距離好友生日的天數(shù)。

          函數(shù)式的方式是:將原始數(shù)據(jù)傳遞給一個函數(shù)或者多個函數(shù),獲得對你的項目有用的數(shù)據(jù)格式。

          4. 面向?qū)ο蟮姆绞?/strong>

          對于編程初學(xué)者和 JavaScript 初學(xué)者,面向?qū)ο蟮母拍羁赡苡悬c難以理解。其思想是,我們要將每個好友變成一個對象,這個對象能夠生成你一切開發(fā)者需要的東西。

          你可以創(chuàng)建一個對象,這個對象對應(yīng)于某個好友,它有 fullName 屬性,還有兩個函數(shù) getThreeRandomPosts 和 getDaysUntilBirthday。

          function initializeFriend(data) {
           return {
           fullName: `${data.firstName} ${data.lastName}`,
           getThreeRandomPosts: function() {
           // get three random posts from data.lastTenPosts
           },
           getDaysUntilBirthday: function() {
           // use data.birthday to get the num days until birthday
           }
           };
          }
          const objectFriends=data.map(initializeFriend)
          objectFriends[0].getThreeRandomPosts() 
          // Gets three of Bob Ross's posts
          

          面向?qū)ο蟮姆绞骄褪菫閿?shù)據(jù)創(chuàng)建對象,每個對象都有自己的狀態(tài),并且包含必要的信息,能夠生成需要的數(shù)據(jù)。

          5. 這跟 this 有什么關(guān)系?

          你也許從來沒想過要寫上面的 initializeFriend 代碼,而且你也許認(rèn)為,這種代碼可能會很有用。但你也注意到,這并不是真正的面向?qū)ο蟆?/p>

          其原因就是,上面例子中的 getThreeRandomPosts 或 getdaysUntilBirtyday 能夠正常工作的原因其實是閉包。因為使用了閉包,它們在 initializeFriend 返回之后依然能訪問 data。關(guān)于閉包的更多信息可以看看這篇文章:作用域和閉包(https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md)。

          還有一個方法該怎么處理?我們假設(shè)這個方法叫做 greeting。注意方法(與 JavaScript 的對象有關(guān)的方法)其實只是一個屬性,只不過屬性值是函數(shù)而已。我們想在 greeting 中實現(xiàn)以下功能:

          function initializeFriend(data) {
           return {
           fullName: `${data.firstName} ${data.lastName}`,
           getThreeRandomPosts: function() {
           // get three random posts from data.lastTenPosts
           },
           getDaysUntilBirthday: function() {
           // use data.birthday to get the num days until birthday
           },
           greeting: function() {
           return `Hello, this is ${fullName}'s data!`
           }
           };
          }
          

          這樣能正常工作嗎?

          不能!

          我們新建的對象能夠訪問 initializeFriend 中的一切變量,但不能訪問這個對象本身的屬性或方法。當(dāng)然你會問,

          難道不能在 greeting 中直接用 data.firstName 和 data.lastName 嗎?

          當(dāng)然可以。但要是想在 greeting 中加入距離好友生日的天數(shù)怎么辦?我們最好還是有辦法在 greeting 中調(diào)用 getDaysUntilBirthday。

          這時輪到 this 出場了!



          6. 終于——this 是什么

          this 在不同的環(huán)境中可以指代不同的東西。默認(rèn)的全局環(huán)境中 this 指代的是全局對象(在瀏覽器中 this 是 window 對象),這沒什么太大的用途。而在 this 的規(guī)則中具有實用性的是這一條:

          如果在對象的方法中使用 this,而該方法在該對象的上下文中調(diào)用,那么 this 指代該對象本身。

          你會說“在該對象的上下文中調(diào)用”……是啥意思?

          別著急,我們一會兒就說。

          所以,如果我們想從 greeting 中調(diào)用 getDaysUntilBirtyday 我們只需要寫 this.getDaysUntilBirthday,因為此時的 this 就是對象本身。

          附注:不要在全局作用域的普通函數(shù)或另一個函數(shù)的作用域中使用 this!this 是個面向?qū)ο蟮臇|西,它只在對象的上下文(或類的上下文)中有意義。

          我們利用 this 來重寫 initializeFriend:

          function initializeFriend(data) {
           return {
           lastTenPosts: data.lastTenPosts,
           birthday: data.birthday, 
           fullName: `${data.firstName} ${data.lastName}`,
           getThreeRandomPosts: function() {
           // get three random posts from this.lastTenPosts
           },
           getDaysUntilBirthday: function() {
           // use this.birthday to get the num days until birthday
           },
           greeting: function() {
           const numDays=this.getDaysUntilBirthday() 
           return `Hello, this is ${this.fullName}'s data! It is ${numDays} until ${this.fullName}'s birthday!`
           }
           };
          }
          

          現(xiàn)在,在 initializeFriend 執(zhí)行結(jié)束后,該對象需要的一切都位于對象本身的作用域之內(nèi)了。我們的方法不需要再依賴于閉包,它們只會用到對象本身包含的信息。

          好吧,這是 this 的用法之一,但你說過 this 在不同的上下文中有不同的含義。那是什么意思?為什么不一定會指向?qū)ο笞约海?/p>

          有時候,你需要將 this 指向某個特定的東西。一種情況就是事件處理函數(shù)。比如我們希望在用戶點擊好友時打開好友的 Facebook 首頁。我們會給對象添加下面的 onClick 方法:

          function initializeFriend(data) {
           return {
           lastTenPosts: data.lastTenPosts,
           birthday: data.birthday,
           username: data.username, 
           fullName: `${data.firstName} ${data.lastName}`,
           getThreeRandomPosts: function() {
           // get three random posts from this.lastTenPosts
           },
           getDaysUntilBirthday: function() {
           // use this.birthday to get the num days until birthday
           },
           greeting: function() {
           const numDays=this.getDaysUntilBirthday() 
           return `Hello, this is ${this.fullName}'s data! It is ${numDays} until ${this.fullName}'s birthday!`
           },
           onFriendClick: function() {
           window.open(`https://facebook.com/${this.username}`)
           }
           };
          }
          

          注意我們在對象中添加了 username 屬性,這樣 onFriendClick 就能訪問它,從而在新窗口中打開該好友的 Facebook 首頁。現(xiàn)在只需要編寫 HTML:

          <button id="Bob_Ross">
           <!-- A bunch of info associated with Bob Ross -->
          </button> 
          

          還有 JavaScript:

          const bobRossObj=initializeFriend(data[0])
          const bobRossDOMEl=document.getElementById('Bob_Ross')
          bobRossDOMEl.addEventListener("onclick", bobRossObj.onFriendClick)
          

          在上述代碼中,我們給 Bob Ross 創(chuàng)建了一個對象。然后我們拿到了 Bob Ross 對應(yīng)的 DOM 元素。然后執(zhí)行 onFriendClick 方法來打開 Bob 的 Facebook 主頁。似乎沒問題,對吧?

          有問題!

          哪里出錯了?

          注意我們調(diào)用 onclick 處理程序的代碼是 bobRossObj.onFriendClick。看到問題了嗎?要是寫成這樣的話能看出來嗎?

          bobRossDOMEl.addEventListener("onclick", function() {
           window.open(`https://facebook.com/${this.username}`)
          })
          

          現(xiàn)在看到問題了嗎?如果把事件處理程序?qū)懗?bobRossObj.onFriendClick,實際上是把 bobRossObj.onFriendClick 上保存的函數(shù)拿出來,然后作為參數(shù)傳遞。它不再“依附”在 bobRossObj 上,也就是說,this 不再指向 bobRossObj。它實際指向全局對象,也就是說 this.username 不存在。似乎我們沒什么辦法了。

          輪到綁定上場了!



          7. 明確綁定 this

          我們需要明確地將 this 綁定到 bobRossObj 上。我們可以通過 bind 實現(xiàn):

          const bobRossObj=initializeFriend(data[0])
          const bobRossDOMEl=document.getElementById('Bob_Ross')
          bobRossObj.onFriendClick=bobRossObj.onFriendClick.bind(bobRossObj)
          bobRossDOMEl.addEventListener("onclick", bobRossObj.onFriendClick)
          

          之前,this 是按照默認(rèn)的規(guī)則設(shè)置的。但使用 bind 之后,我們明確地將 bobRossObj.onFriendClick 中的 this 的值設(shè)置為 bobRossObj 對象本身。

          到此為止,我們看到了為什么要使用 this,以及為什么要明確地綁定 this。最后我們來介紹一下,this 實際上是箭頭函數(shù)。

          8. 箭頭函數(shù)

          你也許注意到了箭頭函數(shù)最近很流行。人們喜歡箭頭函數(shù),因為很簡潔、很優(yōu)雅。而且你還知道箭頭函數(shù)和普通函數(shù)有點區(qū)別,盡管不太清楚具體區(qū)別是什么。

          簡而言之,兩者的區(qū)別在于:

          在定義箭頭函數(shù)時,不管 this 指向誰,箭頭函數(shù)內(nèi)部的 this 永遠(yuǎn)指向同一個東西。

          嗯……這貌似沒什么用……似乎跟普通函數(shù)的行為一樣啊?

          我們通過 initializeFriend 舉例說明。假設(shè)我們想添加一個名為 greeting 的函數(shù):

          function initializeFriend(data) {
           return {
           lastTenPosts: data.lastTenPosts,
           birthday: data.birthday,
           username: data.username, 
           fullName: `${data.firstName} ${data.lastName}`,
           getThreeRandomPosts: function() {
           // get three random posts from this.lastTenPosts
           },
           getDaysUntilBirthday: function() {
           // use this.birthday to get the num days until birthday
           },
           greeting: function() {
           function getLastPost() {
           return this.lastTenPosts[0]
           }
           const lastPost=getLastPost() 
           return `Hello, this is ${this.fullName}'s data!
           ${this.fullName}'s last post was ${lastPost}.`
           },
           onFriendClick: function() {
           window.open(`https://facebook.com/${this.username}`)
           }
           };
          }
          

          這樣能運行嗎?如果不能,怎樣修改才能運行?

          答案是不能。因為 getLastPost 沒有在對象的上下文中調(diào)用,因此getLastPost 中的 this 按照默認(rèn)規(guī)則指向了全局對象。

          你說沒有“在對象的上下文中調(diào)用”……難道它不是從 initializeFriend 返回的內(nèi)部調(diào)用的嗎?如果這還不叫“在對象的上下文中調(diào)用”,那我就不知道什么才算了。

          我知道“在對象的上下文中調(diào)用”這個術(shù)語很模糊。也許,判斷函數(shù)是否“在對象的上下文中調(diào)用”的好方法就是檢查一遍函數(shù)的調(diào)用過程,看看是否有個對象“依附”到了函數(shù)上。

          我們來檢查下執(zhí)行 bobRossObj.onFriendClick() 時的情況。“給我對象 bobRossObj,找到其中的 onFriendClick 然后調(diào)用該屬性對應(yīng)的函數(shù)”。

          我們同樣檢查下執(zhí)行 getLastPost() 時的情況。“給我名為 getLastPost 的函數(shù)然后執(zhí)行。”看到了嗎?我們根本沒有提到對象。

          好了,這里有個難題來測試你的理解程度。假設(shè)有個函數(shù)名為 functionCaller,它的功能就是調(diào)用一個函數(shù):

          functionCaller(fn) {
           fn()
          }
          

          如果調(diào)用 functionCaller(bobRossObj.onFriendClick) 會怎樣?你會認(rèn)為 onFriendClick 是“在對象的上下文中調(diào)用”的嗎?this.username有定義嗎?

          我們來檢查一遍:“給我 bobRosObj 對象然后查找其屬性 onFriendClick。取出其中的值(這個值碰巧是個函數(shù)),然后將它傳遞給 functionCaller,取名為 fn。然后,執(zhí)行名為 fn 的函數(shù)。”注意該函數(shù)在調(diào)用之前已經(jīng)從 bobRossObj 對象上“脫離”了,因此并不是“在對象的上下文中調(diào)用”的,所以 this.username 沒有定義。

          這時可以用箭頭函數(shù)解決這個問題:

          function initializeFriend(data) {
           return {
           lastTenPosts: data.lastTenPosts,
           birthday: data.birthday,
           username: data.username, 
           fullName: `${data.firstName} ${data.lastName}`,
           getThreeRandomPosts: function() {
           // get three random posts from this.lastTenPosts
           },
           getDaysUntilBirthday: function() {
           // use this.birthday to get the num days until birthday
           },
           greeting: function() {
           const getLastPost=()=> {
           return this.lastTenPosts[0]
           }
           const lastPost=getLastPost() 
           return `Hello, this is ${this.fullName}'s data!
           ${this.fullName}'s last post was ${lastPost}.`
           },
           onFriendClick: function() {
           window.open(`https://facebook.com/${this.username}`)
           }
           };
          }
          

          上述代碼的規(guī)則是:

          在定義箭頭函數(shù)時,不管 this 指向誰,箭頭函數(shù)內(nèi)部的 this 永遠(yuǎn)指向同一個東西。

          箭頭函數(shù)是在 greeting 中定義的。我們知道,在 greeting 內(nèi)部的 this 指向?qū)ο蟊旧怼R虼耍^函數(shù)內(nèi)部的 this 也指向?qū)ο蟊旧恚@正是我們需要的結(jié)果。

          9. 結(jié)論

          this 有時很不好理解,但它對于開發(fā) JavaScript 應(yīng)用非常有用。本文當(dāng)然沒能介紹 this 的所有方面。一些沒有涉及到的話題包括:

          • call 和 apply;
          • 使用 new 時 this 會怎樣;
          • 在 ES6 的 class 中 this 會怎樣。

          我建議你首先問問自己在這些情況下的 this,然后在瀏覽器中執(zhí)行代碼來檢驗?zāi)愕慕Y(jié)果。

          原文地址:https://mp.weixin.qq.com/s/L9eac6rzkSE_JqxXyg3FQw

          么是JS延遲加載?

          JS延遲加載,也就是等頁面加載完成之后再加載JavaScript文件

          為什么讓JS實現(xiàn)延遲加載?

          js的延遲加載有助于提高頁面的加載速度。

          Js延遲加載的方式有哪些?一般有以下幾種方式:

          ·defer屬性

          ·async屬性

          ·動態(tài)創(chuàng)建DOM方式

          ·使用jQuery的getScript方法

          ·使用setTimeout延遲方法

          ·讓JS最后加載

          1、defer屬性

          HTML 4.01為<script>標(biāo)簽定義了defer屬性。標(biāo)簽定義了defer屬性元素中設(shè)置defer屬性,等于告訴瀏覽器立即下載,但延遲執(zhí)行標(biāo)簽定義了defer屬性。

          用途:表明腳本在執(zhí)行時不會影響頁面的構(gòu)造。也就是說,腳本會被延遲到整個頁面都解析完畢之后再執(zhí)行在<script>元素中設(shè)置defer屬性,等于告訴瀏覽器立即下載,但延遲執(zhí)行

          <!DOCTYPE html>
          <html>
          <head>
          	<script src="test1.js" defer="defer"></script>
          	<script src="test2.js" defer="defer"></script>
          </head>
          <body>
          <!--這里放內(nèi)容-->
          </body>
          </html>

          說明:雖然<script>元素放在了<head>元素中,但包含的腳本將延遲瀏覽器遇到</html>標(biāo)簽后再執(zhí)行HTML5規(guī)范要求腳本按照它們出現(xiàn)的先后順序執(zhí)行。在現(xiàn)實當(dāng)中,延遲腳本并不一定會按照順序執(zhí)行defer屬性只適用于外部腳本文件。支持HTML5的實現(xiàn)會忽略嵌入腳本設(shè)置的defer屬性

          2、async屬性

          HTML5 為<script>標(biāo)簽定義了async屬性。與defer屬性類似,都用于改變處理腳本的行為。同樣,只適用于外部腳本文件。標(biāo)簽定義了async屬性。與defer屬性類似,都用于改變處理腳本的行為。同樣,只適用于外部腳本文件。

          目的:不讓頁面等待腳本下載和執(zhí)行,從而異步加載頁面其他內(nèi)容。異步腳本一定會在頁面 load 事件前執(zhí)行。不能保證腳本會按順序執(zhí)行

          <!DOCTYPE html>
          <html>
          	<head>
          		<script src="test1.js" async></script>
          		<script src="test2.js" async></script>
          	</head>
          <body>
          <!--這里放內(nèi)容-->
          </body>
          </html>

          async和defer一樣,都不會阻塞其他資源下載,所以不會影響頁面的加載。

          缺點:不能控制加載的順序

          3、動態(tài)創(chuàng)建DOM方式

          //這些代碼應(yīng)被放置在</ body>標(biāo)簽前(接近HTML文件底部)
          <script type="text/javascript">
          	function downloadJSAtOnload() {
          		varelement=document .createElement("script");
          		element.src="defer.js";
          		document.body.appendChild(element);
          	}
          	if (window. addEventListener)
          		window.addEventListener("load" ,downloadJSAtOnload, false);
          	else if (window.attachEvent)
          		window.attachEvent("onload", downloadJSAtOnload) ;
          	else
          		window. onload=downloadJSAtOnload;
          </script>

          4、使用jQuery的getScript()方法

          $.getScript("outer.js" , function(){	//回調(diào)函數(shù),成功獲取文件后執(zhí)行的函數(shù)
          	console.log(“腳本加載完成")
          });

          5、使用setTimeout延遲方法的加載時間延遲加載js代碼,給網(wǎng)頁加載留出更多時間

          <script type="text/javascript" >
          	function A(){
          		$.post("/1ord/1ogin" ,{name:username,pwd:password},function(){
          			alert("Hello");
          		});
          	}
          	$(function (){
          		setTimeout('A()', 1000);	//延遲1秒
          	})
          </script>

          6、讓JS最后加載

          把js外部引入的文件放到頁面底部,來讓js最后引入,從而加快頁面加載速度例如引入外部js腳本文件時,如果放入html的head中,則頁面加載前該js腳本就會被加載入頁面,而放入body中,則會按照頁面從上倒下的加載順序來運行JavaScript的代碼。所以我們可以把js外部引入的文件放到頁面底部,來讓js最后引入,從而加快頁面加載速度。

          上述方法2也會偶爾讓你收到Google頁面速度測試工具的“延遲加載javascript”警告。所以這里的解決方案將是來自Google幫助頁面的推薦方案。

          //這些代碼應(yīng)被放置在</body>標(biāo)簽前(接近HTML文件底部)
          
          <script type="text/javascript">
          	function downloadJSAtonload() {
          		var element=document.createElement("script");
          		element.src="defer.js";
          		document.body.appendChild(element);
          	}
          	if (window.addEventListener)
          		window.addEventListener("load", downloadJSAtOnload, false);
          	else if (window.attachEvent )
          		window.attachEvent("onload", downloadJSAtonload);
          	else window.onload=downloadJSAtOnload;
          </script>

          這段代碼意思等到整個文檔加載完后,再加載外部文件“defer.js”。

          使用此段代碼的步驟:

          6.1)復(fù)制上面代碼

          6.2)粘貼代碼到HTML的標(biāo)簽前 (靠近HTML文件底部)

          6.3)修改“defer.js”為你的外部JS文件名

          6.4)確保文件路徑是正確的。例如:如果你僅輸入“defer.js”,那么“defer.js”文件一定與HTML文件在同一文件夾下。

          注意:

          這段代碼直到文檔加載完才會加載指定的外部js文件。因此,不應(yīng)該把那些頁面正常加載需要依賴的javascript代碼放在這里。而應(yīng)該將JavaScript代碼分成兩組。一組是因頁面需要而立即加載的javascript代碼,另外一組是在頁面加載后進(jìn)行操作的javascript代碼(例如添加click事件。

          avascript原生阻止冒泡

          <html>
          <head>
          <style type="text/css">
          #hide{width:75%;height:80px;background:skyblue;display:block;}
          .hander{cursor:pointer;}
          input{margin:5 0 0 900;}
          </style>
          <script>
              //不用window.onload也可以
              document.documentElement.onclick=function() {
              		document.getElementById('hide').style.display='none';
              }
          //阻止冒泡事件方法
          function stopBubble(e) {
              e=e || window.event;
              if(e.stopPropagation) { //W3C阻止冒泡方法
              e.stopPropagation();
              } else {
              e.cancelBubble=true; //IE阻止冒泡方法
              }
          }
          //方法必須要放在window.onload下
          window.onload=function(){
              document.getElementById("hide").onclick=function(e) {
              stopBubble(e);
              }
              document.getElementById('btn_show').onclick=function(e) {
              document.getElementById('hide').style.display='block';
              stopBubble(e);
              }
          }
          </script>
          </head>
          <body>
          <div id="hide" class="hander">click here nothing happen,you can click beside this area</div>
          <input type="button" id="btn_show" value="show" class="hander"/>
          </body>
          onclick 如何阻止事件冒泡
          <div id="id_tag_list"><span class="right">▼</span><span class="label" onclick="deleteLabel(this)">Python數(shù)據(jù)分析與應(yīng)用</span></div>
          //刪除標(biāo)簽的方法
          function deleteLabel(target){
              var e=target;
              if(e && e.stopPropagation){ //阻止冒泡
                // 因此它支持W3C的stopPropation()方法
                e.stopPropagation();
              }else{
                // 否則, 我們得使用IE的方法來取消事件冒泡
                window.event.cancelBubble=true;
              }
          }

          jQuery如何阻止事件冒泡

          <div class="subcategories">這里有點擊事件</div>
          <div class="subcategories">這里有點擊事件</div>
          <div class="subcategories">這里有點擊事件</div>


          <script type="text/javascript">
          //阻止點擊事件
          $(function() {
              $(".subcategories").click(function(event) {
                  event.stopPropagation();
              });
          });
          </script>

          什么是js事件冒泡?

          在一個對象上觸發(fā)某類事件(比如單擊onclick事件), 如果此對象定義了此事件的處理程序, 那么此事件就會調(diào)用這個處理程序, 如果沒有定義此事件處理程序或者事件返回true,

          那么這個事件會向這個對象的父級對象傳播, 從里到外, 直至它被處理(父級對象所有同類事件都將被激活), 或者它到達(dá)了對象層次的最頂層, 即document對象(有些瀏覽器是window)。

          如何來阻止Jquery事件冒泡?

          <!DOCTYPE html>
          <html">
          <head runat="server">
          <title>Jquery 事件冒泡</title>
          <script src="jquery-1.3.2-vsdoc.js" type="text/javascript"></script>
          </head>
          <body>
            <form id="form1" runat="server">
              <div id="divOne" onclick="alert('我是最外層');">
                <div id="divTwo" onclick="alert('我是中間層!')">
                  <a id="hr_three" href="http://www.xxxxxx.com" mce_href="http://www.xxxxxx.com"onclick="alert('我是最里層!')">點擊我</a>
                </div>
              </div>
            </form>
          </body>
          </html>

          比如上面這個頁面,

          分為三層:divOne是第外層,divTwo中間層,hr_three是最里層;

          他們都有各自的click事件,最里層a標(biāo)簽還有href屬性。

          運行頁面,點擊“點擊我”,會依次彈出:我是最里層---->我是中間層---->我是最外層

          ---->然后再鏈接到百度.


          這就是事件冒泡, 本來我只點擊ID為hr_three的標(biāo)簽, 但是確執(zhí)行了三個alert操作。

          事件冒泡過程(以標(biāo)簽ID表示):hr_three----> divTwo----> divOne 。從最里層冒泡到最外層。

          如何來阻止?

          1.event.stopPropagation();

          <script type="text/javascript">
          $(function() {
          $("#hr_three").click(function(event) {
          event.stopPropagation();
          });
          });
          <script>

          再點擊"點擊我", 會彈出:我是最里層, 然后鏈接到百度


          2.return false;

          如果頭部加入的是以下代碼

          <script type="text/javascript">
          $(function() {
            $("#hr_three").click(function(event) {
              return false;
            });
          });
          <script>

          再點擊"點擊我", 會彈出:我是最里層, 但不會執(zhí)行鏈接到百度頁面


          由此可以看出:

          1.event.stopPropagation();

          事件處理過程中,阻止了事件冒泡,但不會阻擊默認(rèn)行為(它就執(zhí)行了超鏈接的跳轉(zhuǎn))


          2.return false;

          事件處理過程中,阻止了事件冒泡,也阻止了默認(rèn)行為(比如剛才它就沒有執(zhí)行超鏈接的跳轉(zhuǎn))


          還有一種有冒泡有關(guān)的:

          3.event.preventDefault();

          如果把它放在頭部A標(biāo)簽的click事件中, 點擊"點擊我"。

          會發(fā)現(xiàn)它依次彈出:我是最里層---->我是中間層---->我是最外層, 但最后卻沒有跳轉(zhuǎn)到百度

          它的作用是:事件處理過程中, 不阻擊事件冒泡, 但阻擊默認(rèn)行為(它只執(zhí)行所有彈框, 卻沒有執(zhí)行超鏈接跳轉(zhuǎn))


          上一篇:JavaScript第一步
          下一篇:CSS font-style 屬性
          主站蜘蛛池模板: 日韩精品一区二区三区视频 | 精品乱人伦一区二区三区| 在线欧美精品一区二区三区 | 色综合视频一区二区三区44| 亚洲国产av一区二区三区丶| 国产一区二区三区播放心情潘金莲| 亚洲爆乳精品无码一区二区| 久久se精品一区二区影院| 亚洲av无码一区二区三区在线播放| 国产伦精品一区三区视频| 骚片AV蜜桃精品一区| 丝袜人妻一区二区三区| 国产精品久久久久一区二区三区| 国产一区二区精品在线观看| 亚洲综合一区二区精品导航| 国产成人片视频一区二区| 黑人一区二区三区中文字幕| 一区二区精品视频| 精品福利一区二区三区| 亚洲一区在线免费观看| 影院无码人妻精品一区二区| 日韩A无码AV一区二区三区 | 国产福利在线观看一区二区 | 亚洲综合一区二区国产精品| 日本无卡码一区二区三区| 成人在线视频一区| 色偷偷一区二区无码视频| 国产精品成人一区无码| 久久精品一区二区| 精品亚洲福利一区二区| 最美女人体内射精一区二区| 精品日韩一区二区| 国产自产在线视频一区| 国产日韩视频一区| 精品人无码一区二区三区| 亚洲国产成人久久一区WWW| 精品国产伦一区二区三区在线观看 | 久久国产高清一区二区三区| 丰满人妻一区二区三区免费视频| 国产午夜福利精品一区二区三区 | 一区二区在线视频观看|