引言
今天的直播課老師會通過js的事件機制來模仿淘寶註冊頁面表單驗證效果,實現效果如下:
怎麼樣,感興趣的小夥伴抓緊入群了,獲取直播通知,觀看直播。
下面給大家總結了下js中的事件講解。
事件流
多個彼此嵌套的元素,他們擁有相同的時間,最內部事件被觸發后,外邊多個元素的同類型時間會被觸發,多個元素他們同類型時間同時執行的效果稱為」事件流」
注意:在addEventListener或者removeEventListener中最後一個參數如果為false(冒泡型,從內而外),為true(捕捉型,從外而內)
事件對象
事件對象,每個事件(包括滑鼠,鍵盤事件)觸發執行的過程中,都有對應的事件對象,通過事件對象可以獲得滑鼠相對頁面的坐標信息,什麼鍵子被觸發執行,通過事件對象還可以阻止事件流產生,阻止瀏覽器默認動作。
1.獲得事件對象
聲明觸發方法時參數evt,evt就是事件對象
2.獲取滑鼠的坐標信息
event.clientX/clientY (相對dom的坐標)
event.pageX/pageY (考慮滾動條)
event.screenX/screenY (相對屏幕坐標)
3.阻止事件流
event.stopPropagetion //主流瀏覽器
event.cancelBubble = true //IE瀏覽器 冒泡型、捕捉型都可以進行阻止
4.阻止瀏覽器默認動作
事件對象.preventDefault //主流瀏覽器
事件對象.returnValue=false //IE瀏覽器 return false //dom1級事件設置
5.獲取被觸發鍵盤鍵子信息
event.keyCode 獲得鍵盤對應的鍵值碼信息,返回的為ASC碼
載入事件 onload
JS代碼執行時如果涉及到html或者css時,需要讓html和css執行后,在執行js代碼,但通過載入事件可以實現JS代碼寫在html和css代碼之前
具體設置:
//方式1(不推薦)
<body onload=「載入函數」>
//方式2 //在js中書寫
window.load=載入函數;
javascript事件綁定
事件綁定就是給目標(DOM元素)綁定觸發事件(如click)、觸發事件產生的結果(fn)以及事件獲取方式(useCapture)。事件綁定分為普通事件綁定、事件監聽和事件委託;
1.普通事件綁定之html屬性綁定
2.普通事件綁定之javascript綁定
同一個觸發事件只會觸發最後一個事件,前面的被覆蓋掉了,2比1的優點是,實現結構和行為分離,利於代碼的管理和維護
事件監聽
優點:
1)可以綁定多個事件
2)可以移出事件;如:oBtn.removeEventListener("click",aaa);
3 ) addEventListener("事件",fn,useCapture);
這種寫法有4個要注意的地方:
事件帶on並且加引號("click");
fn不加括弧,加括弧等於調用了fn;
useCapture的意思為捕獲,但是默認為冒泡(false),可以省略不寫
不兼容IE8以下
兼容寫法:attachEvent("on+事件",fn);
經過測試,attachEvent兼容了IE6,但是事件執行的順序是相反的,IE7不兼容attachEvent,這裡有可能是這個IE兼容測試器出問題了,否則這個寫法不兼容IE7。
IE的綁定事件 attachEvent("on事件",listener)
綁定事件 addEventListener("事件",listener,useCapture)
兩個監聽事件的區別:
事件有無on,有無true/false,事件執行順序相反
this指向的問題:在IE6-9之間都存在一個問題就是this指向的是window
事件委託
利用冒泡,把事件加到父元素或祖先元素上
優點:
1)提高JavaScript性能。事件委託可以顯著的提高事件的處理速度,減少內存的佔用。
2)動態的添加DOM元素,不需要因為元素的改動而修改事件綁定。
3)兼容到IE6,但是IE7,IE8還是沒反應。
js事件循環機制
事件循環機制呢,簡單點來說,就是在執行上下文的過程中,對函數的入棧和出棧。執行前函數先入棧,執行完后函數出棧。如若遇到了一些非同步操作像回調函數以及ajax、setTimeout等,會先將他們交給瀏覽器的其他模塊去執行,執行完后,會把回調函數放入到taskqueue中。當所有的call stack執行完后再開始執行task queue中的函數。
舉一個簡單的例子:
我們來看一下執行的內部過程
1. 執行第一句,放入call stack中,輸出 1
2. 第一句出棧,執行第二句,由於是非同步執行,交給其他模塊。
3. 執行完后,將回調函數放入taskqueue中 。
4. 執行下一句,同第一步一樣,將語句入棧並執行,輸出3 。
5. 語句出棧,此時call stack空了。開始執行task queue任務,輸出2 。
所以,輸出結果是 :
進階
如果添加了Promise又如何工作呢?
我們知道,Promise的回調函數不是傳入的,而是使用then來調用的。因此,Promise中定義的函數應該是馬上執行的,then才是其回調函數,放入queue隊列中。
還提到了一個重要的概念:
macro-task包括:script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver
執行順序:函數調用棧清空只剩全局執行上下文,然後開始執行所有的micro-task。當所有可執行的micro-task執行完畢之後。循環再次執行macro-task中的一個任務隊列,執行完之後再執行所有的micro-task,就這樣一直循環。
執行過程:
1. 遇到setTimeout,交給其他模塊執行,執行完后回調放入macro-task中
2. 遇到Promise,立即執行裡面的function,輸出1。
3. 循環開始,遇到resolve,修改Promise狀態為fulfill。繼續執行,輸出2。
4. 遇到then,將回調放入micro-task中。
5. 繼續執行,輸出3。
6. call stack執行完畢了。開始執行micro-task中的回調函數,輸出5。
7. micro-task執行完畢,開始執行macro-task中的回調函數,輸出4。
8. 結束。