丸子學JS(學習2小時 - 事件處理)

事件

  • addEventListener 用來處理多個事件同時綁定
 element.addEventListener(event, handler[, options]);

handler 事件處理程序, event 事件對象,handleEvent 對象處理程序

冒泡和捕獲

  • 冒泡

當一個事件發(fā)生在一個元素上蹲缠,它會首先運行在該元素上的處理程序费就,然后運行其父元素上的處理程序咖城,然后一直向上到其他祖先上的處理程序

  • event.target

引發(fā)事件的那個嵌套層級最深的元素被稱為目標元素,可以通過 event.target 訪問

停止冒泡
event.stopPropagation()用于停止冒泡

event.stopImmediatePropagation() 用于停止冒泡十绑,并阻止當前元素上的處理程序運行。使用該方法之后慧瘤,其他處理程序就不會被執(zhí)行

捕獲
DOM事件標準描述了事件傳播的 3 個階段:

  1. 捕獲階段(Capturing phase)—— 事件(從 Window)向下走近元素戴已。
  2. 目標階段(Target phase)—— 事件到達目標元素。
  3. 冒泡階段(Bubbling phase)—— 事件從元素上開始冒泡锅减。
    如果要在捕獲階段捕獲事件 糖儡,需要將處理程序的 capture選項設置為 true
ele.addEventListener(..., {capture: true})
ele.addEventListener(..., true)

事件委托

如果我們有許多以類似方式處理的元素,那么就不必為每個元素分配一個處理程序 —— 而是將單個處理程序放在它們的共同祖先上

  • 行為模式
  1. 行為: 計數器
var btn = document.querySelector("button");
var num = 0;
btn.onclick = function (){
  btn.innerHTML = ++num;
  if(btn.innerText == 10){
    alert("不累么怔匣?握联?")
    btn.style.background = "orange";
  }
}
  1. 行為:切換器
<div class="wrapper">
    <button data-toggle-id="changeBox">點擊切換</button>
    <div id="changeBox"></div>

</div>
<script>
    let btn = document.querySelector('button')
    btn.addEventListener('click', function(event){
        let id = event.target.dataset.toggleId;
        if(!id) return 
        let ele = document.querySelector('#'+id)
        ele.style.display == 'none' ?
        ele.style.display = 'block':
        ele.style.display = 'none'
    })
</script>

瀏覽器默認行為

event.preventDefault() 用于阻止默認行為,如果處理程序是使用 on<event>(而不是 addEventListener)分配的,那返回 false 也同樣有效

創(chuàng)建自定義事件

  • 事件構造器
let event = new Event(type[,options])

type —— 事件類型拴疤,可以是像這樣 "click" 的字符串永部,或者我們自己的像這樣 "my-event" 的參數
options —— 具有兩個可選屬性的對象:默認情況下独泞,以上兩者都為 false:{bubbles: false, cancelable: false}

  • 觸發(fā)
    通過使用 elem.dispatchEvent(event)調用在元素上“運行”
  • 其他一些事件
    ● UIEvent
    ● FocusEvent
    ● MouseEvent
    ● WheelEvent
    ● KeyboardEvent
let event = new MouseEvent("click", {
  bubbles: true,
  cancelable: true,
  clientX: 100,
  clientY: 100
});
  • 自定義事件
<h1 id="elem">Hello for John!</h1>

<script>
  // 事件附帶給處理程序的其他詳細信息
  elem.addEventListener("hello", function(event) {
    alert(event.detail.name);
  });

  elem.dispatchEvent(new CustomEvent("hello", {
    detail: { name: "John" }
  }));
</script>

鼠標事件

  • 鼠標事件類型

mousedown / mouseup
在元素上點擊/釋放鼠標按鈕

mouseover / mouseout
鼠標指針從一個元素上移入/移出

mousemove
鼠標在元素上的每個移動都會觸發(fā)此事件

click
果使用的是鼠標左鍵呐矾,則在同一個元素上的 mousedown 及 mouseup 相繼觸發(fā)后,觸發(fā)該事件

dblclick
在短時間內雙擊同一元素后觸發(fā)

contextmenu
在鼠標右鍵被按下時觸發(fā)

  • 事件順序
    在單個動作觸發(fā)多個事件時懦砂, 事件的順序是固定的蜒犯,會遵循 mousedown -> mouseup -> click 的順序調用處理程序

  • 鼠標按鈕
    使用 button 屬性來區(qū)分是左鍵單擊還是右鍵單擊

  • 組合鍵: shift、alt荞膘、ctrl罚随、meta
    事件屬性:
    ● shiftKey:Shift
    ● altKey:Alt(或對于 Mac 是 Opt)
    ● ctrlKey:Ctrl
    ● metaKey:對于 Mac 是 Cmd

  • 坐標: clientX/Y, pageX/Y

  1. 相對于窗口的坐標:clientX 和 clientY。
  2. 相對于文檔的坐標:pageX 和 pageY
  • 防止在鼠標按下時的選擇
    防止瀏覽器對 mousedown進行操作羽资,可以阻止鼠標按下時的選擇
Before...
<b ondblclick="alert('Click!')" onmousedown="return false">
  Double-click me
</b>
...After

通過使用oncopy事件淘菩, 可以防止用戶復制

<div oncopy="alert('Copying forbidden!');return false">
  Dear user,
  The copying is forbidden for you.
  If you know JS or HTML, then you can get everything from the page source though.
</div>

移動鼠標: mouseover/out , mouseenter/leave

  • 事件mouseover/mouseout, relatedTarget
    當鼠標指針移到某個元素上時屠升,mouseover 事件就會發(fā)生潮改,而當鼠標離開該元素時,mouseout 事件就會發(fā)生

    對于mouseover:
    ● event.target —— 是鼠標移過的那個元素腹暖。
    ● event.relatedTarget —— 是鼠標來自的那個元素(relatedTarget → target)
  • 跳過元素

    注意: 如果 mouseover被觸發(fā)了汇在, 則必須有 mouseout
  • 事件 mouseenter和mouseleave
    事件 mouseenter/mouseleave 類似于 mouseover/mouseout。它們在鼠標指針進入/離開元素時觸發(fā)
  1. 元素內部與后代之間的轉換不會產生影響脏答。
  2. 事件 mouseenter/mouseleave 不會冒泡糕殉。

鼠標拖放事件

  • 拖放算法
  1. 在 mousedown 上 —— 根據需要準備要移動的元素(也許創(chuàng)建一個它的副本,向其中添加一個類或其他任何東西)
  2. 然后在 mousemove 上殖告,通過更改 position:absolute 情況下的 left/top 來移動它
  3. 在 mouseup 上 —— 執(zhí)行與完成的拖放相關的所有行為
ball.onmousedown = function(event) {
  // (1) 準備移動:確保 absolute阿蝶,并通過設置 z-index 以確保球在頂部
  ball.style.position = 'absolute';
  ball.style.zIndex = 1000;

  // 將其從當前父元素中直接移動到 body 中
  // 以使其定位是相對于 body 的
  document.body.append(ball);

  // 現在球的中心在 (pageX, pageY) 坐標上
  function moveAt(pageX, pageY) {
    ball.style.left = pageX - ball.offsetWidth / 2 + 'px';
    ball.style.top = pageY - ball.offsetHeight / 2 + 'px';
  }

  // 將我們絕對定位的球移到指針下方
  moveAt(event.pageX, event.pageY);

  function onMouseMove(event) {
    moveAt(event.pageX, event.pageY);
  }

  // (2) 在 mousemove 事件上移動球
  document.addEventListener('mousemove', onMouseMove);

  // (3) 放下球,并移除不需要的處理程序
  ball.onmouseup = function() {
    document.removeEventListener('mousemove', onMouseMove);
    ball.onmouseup = null;
  };
};

為防止瀏覽器自己的拖放處理與我們的拖放處理產生沖突黄绩,需禁用它

ball.ondragstart = function() {
  return false;
};
  • 修正定位
ball.onmousedown = function(event) {

  let shiftX = event.clientX - ball.getBoundingClientRect().left;
  let shiftY = event.clientY - ball.getBoundingClientRect().top;

  ball.style.position = 'absolute';
  ball.style.zIndex = 1000;
  document.body.append(ball);

  moveAt(event.pageX, event.pageY);

  // 移動現在位于坐標 (pageX, pageY) 上的球
  // 將初始的偏移考慮在內
  function moveAt(pageX, pageY) {
    ball.style.left = pageX - shiftX + 'px';
    ball.style.top = pageY - shiftY + 'px';
  }

  function onMouseMove(event) {
    moveAt(event.pageX, event.pageY);
  }

  // 在 mousemove 事件上移動球
  document.addEventListener('mousemove', onMouseMove);

  // 放下球羡洁,并移除不需要的處理程序
  ball.onmouseup = function() {
    document.removeEventListener('mousemove', onMouseMove);
    ball.onmouseup = null;
  };
};

ball.ondragstart = function() {
  return false;
};
  • 潛在的放置目標
    有一個叫做 document.elementFromPoint(clientX, clientY) 的方法。它會返回在給定的窗口相對坐標處的嵌套的最深的元素(如果給定的坐標在窗口外宝与,則返回 null)
    基于 onMouseMove 擴展的代碼焚廊,用于查找 “droppable” 的元素
// 我們當前正在飛過的潛在的 droppable 的元素
let currentDroppable = null;

function onMouseMove(event) {
  moveAt(event.pageX, event.pageY);

  ball.hidden = true;
  let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
  ball.hidden = false;

  // mousemove 事件可能會在窗口外被觸發(fā)(當球被拖出屏幕時)
  // 如果 clientX/clientY 在窗口外,那么 elementfromPoint 會返回 null
  if (!elemBelow) return;

  // 潛在的 droppable 的元素被使用 "droppable" 類進行標記(也可以是其他邏輯)
  let droppableBelow = elemBelow.closest('.droppable');

  if (currentDroppable != droppableBelow) {
    // 我們正在飛入或飛出...
    // 注意:它們兩個的值都可能為 null
    //   currentDroppable=null —— 如果我們在此事件之前习劫,鼠標指針不是在一個 droppable 的元素上(例如空白處)
    //   droppableBelow=null —— 如果現在咆瘟,在當前事件中,我們的鼠標指針不是在一個 droppable 的元素上

    if (currentDroppable) {
      // 處理“飛出” droppable 的元素時的處理邏輯(移除高亮)
      leaveDroppable(currentDroppable);
    }
    currentDroppable = droppableBelow;
    if (currentDroppable) {
      // 處理“飛入” droppable 的元素時的邏輯
      enterDroppable(currentDroppable);
    }
  }
}

鍵盤: keydown 和 keyup

當一個按鍵被按下時诽里,會觸發(fā)keydown事件袒餐,而當按鍵被釋放時,會觸發(fā)keyup事件。
注意: event.codeevent.key
事件對象的 key 屬性允許獲取字符灸眼,而事件對象的 code 屬性則允許獲取“物理按鍵代碼”

滾動

  • 防止?jié)L動
    只能在 pageUp和pageDown的 keydown事件上卧檐, 使用event.preventDefault() 來阻止?jié)L動

表單屬性和方法

  • 導航: 表單和元素
    文檔中的表單是特殊集合 document.forms 的成員
  • input和textarea
    通過 input.value(字符串)或 input.checked(布爾值)來訪問復選框(checkbox)中的它們的 value

聚焦: focus / blur

  • focus/blur 事件
    當元素聚焦時,會觸發(fā)focus事件焰宣,當元素失去焦點時霉囚,會觸發(fā)blur事件
  • focus/blur方法
    elem.focus()elem.blur() 方法可以設置和移除元素上的焦點
  • 允許在任何元素上聚焦: tabindex
點擊第一項,然后按 Tab 鍵匕积。跟蹤順序盈罐。請注意,多按幾次 Tab 鍵后闪唆,會將焦點移到這個通過 iframe 嵌入的示例的外面盅粪。
<ul>
  <li tabindex="1">One</li>
  <li tabindex="0">Zero</li>
  <li tabindex="2">Two</li>
  <li tabindex="-1">Minus one</li>
</ul>

<style>
  li { cursor: pointer; }
  :focus { outline: 1px dashed green; }
</style>
  • focus/blur 委托
    focus 和 blur 事件不會向上冒泡。
    使用 focusin 和 focusout 事件 —— 與 focus/blur 事件完全一樣悄蕾,只是它們會冒泡票顾。
    值得注意的是,必須使用 elem.addEventListener 來分配它們帆调,而不是 on<event>

表單事件: change奠骄, input, cut贷帮, copy戚揭, paste

  • 事件: change
    當元素更改完成時, 將觸發(fā)change事件
<input type="text" onchange="alert(this.value)">
  • 事件: input
    每當用戶對輸入值進行修改后撵枢, 就會觸發(fā)input 事件
  • 事件: cut民晒、copy、paste
    這些事件發(fā)生于剪切/拷貝/粘貼一個值的時候
    它們屬于 ClipboardEvent類锄禽, 并提供了對剪切/拷貝/粘貼的數據的訪問方法
<input type="text" id="input">
<script>
  input.onpaste = function(event) {
    alert("paste: " + event.clipboardData.getData('text/plain'));
    event.preventDefault();
  };

  input.oncut = input.oncopy = function(event) {
    alert(event.type + '-' + document.getSelection());
    event.preventDefault();
  };
</script>
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末潜必,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子沃但,更是在濱河造成了極大的恐慌磁滚,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宵晚,死亡現場離奇詭異垂攘,居然都是意外死亡,警方通過查閱死者的電腦和手機淤刃,發(fā)現死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門晒他,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逸贾,你說我怎么就攤上這事陨仅〗蛑停” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵灼伤,是天一觀的道長触徐。 經常有香客問我,道長狐赡,這世上最難降的妖魔是什么撞鹉? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮猾警,結果婚禮上孔祸,老公的妹妹穿的比我還像新娘。我一直安慰自己发皿,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布拂蝎。 她就那樣靜靜地躺著穴墅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪温自。 梳的紋絲不亂的頭發(fā)上玄货,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音悼泌,去河邊找鬼松捉。 笑死,一個胖子當著我的面吹牛馆里,可吹牛的內容都是我干的隘世。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼鸠踪,長吁一口氣:“原來是場噩夢啊……” “哼丙者!你這毒婦竟也來了?” 一聲冷哼從身側響起营密,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤械媒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后评汰,有當地人在樹林里發(fā)現了一具尸體纷捞,經...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年被去,在試婚紗的時候發(fā)現自己被綠了主儡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡编振,死狀恐怖缀辩,靈堂內的尸體忽然破棺而出臭埋,到底是詐尸還是另有隱情,我是刑警寧澤臀玄,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布瓢阴,位于F島的核電站,受9級特大地震影響健无,放射性物質發(fā)生泄漏荣恐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一累贤、第九天 我趴在偏房一處隱蔽的房頂上張望叠穆。 院中可真熱鬧,春花似錦臼膏、人聲如沸硼被。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嚷硫。三九已至,卻和暖如春始鱼,著一層夾襖步出監(jiān)牢的瞬間仔掸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工医清, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留起暮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓会烙,卻偏偏與公主長得像负懦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子持搜,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內容