“捕獲組”是正則表達(dá)式中的概念,除了 JavaScript,在其他正則表達(dá)式的應(yīng)用場景中也都是通用的。下面主要以 JavaScript 中的捕獲組為例說明。
創(chuàng)新互聯(lián)建站是專業(yè)的新巴爾虎左網(wǎng)站建設(shè)公司,新巴爾虎左接單;提供網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì),網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行新巴爾虎左網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!
首先,在正則表達(dá)式中,可以進(jìn)行“分組”,用一對圓弧括號括起來的表達(dá)式就是一個分組。
/(pattern)/?//?JS?中分組的基本寫法
比如,“/(sun)(day)/”就表示了由“sun”和“day”子表達(dá)式構(gòu)成的兩個分組,它最終的匹配效果和“/sunday/”一致,只是分組之后可以將各組子表達(dá)式的匹配結(jié)果分別處理,操作更加靈活。其實(shí),這兩個分組也是捕獲組。
捕獲組就是將正則表達(dá)式中子表達(dá)式匹配的結(jié)果,分組按順序保存,之后可以通過序號或名稱來使用這些內(nèi)容。不過,暫時 JavaScript 還不支持為捕獲組命名,因此也就無法通過名稱來訪問捕獲組,只能通過序號訪問。
下面舉3個匹配簡單整數(shù)四則運(yùn)算的例子,介紹一下捕獲組的基本用法。
1)通過捕獲組分別讀取前運(yùn)算數(shù)、運(yùn)算符和后運(yùn)算數(shù):
var?reg1=/(\d+)([\+\-\*\/])(\d+)/;
var?matches=reg1.exec("10*20");
var?comp=matches[0];?//"10*20"
//序號0為匹配的內(nèi)容,分組從1開始
var?num1=matches[1];?//"10"
var?sign=matches[2];?//"*"
var?num2=matches[3];?//"20"
捕獲組還能反向引用,即在表達(dá)式中直接使用某個分組的內(nèi)容。
2)匹配前、后兩個數(shù)值的相同情況:
var?reg2=/(\d+)([\+\-\*\/])\1/;?//反向引用時用“\+序號”即可
var?result1=reg2.test("25-25");?//true
var?result2=reg2.test("25-14");?//false
3)置換前、后兩個數(shù)的位置(使用例 1 中的正則表達(dá)式):
var?str="234/156";
var?change=str.replace(reg1,"$3$2$1");?//"156/234"
//?在?replace?語句中引用的寫法是“$+序號”
既然有捕獲組,那肯定還有非捕獲組。顧名思義,只執(zhí)行匹配過程、不保存匹配結(jié)果的分組就是非捕獲組。在捕獲組表達(dá)式的左括號后加“?”和“:”等符號即可構(gòu)成非捕獲組。
/(?:pattern)/?//?JS?中非捕獲組的基本寫法
與非捕獲組相關(guān)的還有“預(yù)查”,這些擴(kuò)展知識就不多介紹了,感興趣的話可以自行查找。
? 以click點(diǎn)擊事件為例。假如我們有一個多層結(jié)構(gòu)標(biāo)簽。如下圖,是4個div嵌套。每個div都有點(diǎn)擊的監(jiān)聽事件,分別輸出1234。當(dāng)我們點(diǎn)擊最里面的div時,點(diǎn)擊事件開始傳遞,傳遞的 全過程是1-2-3-4-4-3-2-1 。
前半部分,事件從最外面的父div依次傳遞到最里面的后代div, 1-2-3-4這部分我們叫捕獲過程 。
之后事件又從最里層的后代div逐層傳出, 4-3-2-1這部分我們叫冒泡過程 。
如果我把捕獲監(jiān)聽器和冒泡監(jiān)聽器都加上,如下圖這樣。
這時我們有8個監(jiān)聽器了,在捕獲過程和冒泡過程都有監(jiān)聽。輸出如下圖。
如果我去除幾個監(jiān)聽器如下圖。為了容易理解我調(diào)整了格式
仍然是按照箭頭順序,明顯應(yīng)該輸出1423。
在不使用任何框架的情況下,我們在js中通過addEventListener方法給Dom添加事件監(jiān)聽。這個方法有三個參數(shù)可以傳遞addEventListener(event,fn,useCapture)。event是事件類型click,focus,blur等;fn是事件觸發(fā)時將執(zhí)行的函數(shù)方法(function);第三個參數(shù)可以不傳,默認(rèn)是false,這個參數(shù)控制是否捕獲觸發(fā)。所以我們只穿兩個參數(shù)時,這個事件是冒泡傳遞觸發(fā)的,當(dāng)?shù)谌齻€參數(shù)存在且為true時,事件是捕獲傳遞觸發(fā)的。
? ? 使用框架時可使用對應(yīng)的框架提供的方法。如上面我使用了Vue框架,通過事件裝飾來區(qū)分捕獲與冒泡。
? ? 在不使用任何框架的情況下,我們在js中通過stopPropagation方法阻止事件繼續(xù)傳遞。
使用框架時可使用對應(yīng)的框架提供的方法。接下來我將了Vue框架的stop修飾符來阻止事件傳遞。
? ? 我們可以在傳遞過程中阻止事件繼續(xù)傳遞,防止觸發(fā)不需要的事件。
如圖我在第三層捕獲后阻止事件繼續(xù)傳遞,那么后面的log方法不會繼續(xù)執(zhí)行。最終只輸出1-2-3。
? ? 我們在使用中多數(shù)情況下只使用冒泡監(jiān)聽。例如一條購物車信息,在這條信息中,右下角有一個刪除按鈕。點(diǎn)擊這條消息可查看詳情,點(diǎn)擊刪除按鈕可將此商品移除。我們會分別給信息的div和刪除button添加一個冒泡的click事件監(jiān)聽。如果不做阻止傳遞,點(diǎn)擊刪除button后,會顯示商品詳情。顯然這不是我們想看到的。這時我們給button一個阻止事件傳遞的功能,點(diǎn)擊刪除按鈕后,事件就會結(jié)束,就不再顯示商品詳情。
前端豆知識,很小卻有用
瀏覽器中對事件的處理機(jī)制默認(rèn)為事件冒泡,例如
div id='div1'div id='div2'div id='div3'/div/div/div
#div1{ width: 500px;height: 500px; background: rgb(12,42,31);}#div2{ width: 450px;height: 450px; background: rgb(212,142,1);}#div3{ width: 350px;height: 350px; background: rgb(1,242,153);}
綁定click事件:
div1.onclick=function(){ alert("div1")}div2.onclick=function(){ alert("div2")}div3.onclick=function(){ alert("div3")}
此時,當(dāng)單擊中間的div3時,先后彈出div3, div2, div1,此為事件冒泡的過程。利用addEventListener可以設(shè)置事件處理機(jī)制為捕獲還是冒泡:
div1.addEventListener('click',function(obj){ alert("div1")},true);//如果未false則為事件冒泡,不填的話,默認(rèn)falsediv2.addEventListener('click',function(obj){ alert("div2")},true);div3.addEventListener('click',function(obj){ alert("div3")},true);
這里將第三個參數(shù)設(shè)為true,指定事件處理機(jī)制為事件捕獲。此時再次單擊div3時,會依次彈出div1, div2, div3,與之前的相反。
而IE中只有事件冒泡,且沒有addEventListener事件,取而代之的是attachEvent。
但是有時候,我們不喜歡出現(xiàn)事件冒泡或者捕獲,希望單擊div3時,只彈出div3。這時就要用到下面阻止事件冒泡的方法。
1. 阻止冒泡事件
主要是用于阻止事件傳播。阻止它被分派到其他的DOM節(jié)點(diǎn)上,在事件傳播的任何階段都能使用。使用方法如下(兼容IE):
function stopBubble(event){ if(window.event){//兼容IE window.event.cancelBubble=true; }else{ event.stopPropagation(); }
2. 阻止默認(rèn)事件
像submit這類的表單元素,都會綁定默認(rèn)事件,如果不阻止默認(rèn)事件,則綁定的其他方法也會無效。使用方法如下(兼容IE):
function stopDefaultEvent(event){ if(window.event){//兼容IE window.event.returnValue=false; }else{ event.preventDefault() } return false;}