1. 程式人生 > >vue.js - 奇怪的 event 對象

vue.js - 奇怪的 event 對象

vue 兼容 性問題 select 返回 打印 獲取 origin 接收

好久都沒有寫點東西了, 前段時間工作搞得頭大,真的就是一起加班到死了。廢話不多說,寫這篇文章是因為這次因為 event 對象鬧了一個烏龍,以此總結一下。

一、event 對象

(一)事件的 event 對象

你說你是搞前端的,那麽你肯定就知道事件,知道事件,你就肯定知道 event 對象吧?各種的庫、框架多少都有針對 event 對象的處理。比如 jquery,通過它內部進行一定的封裝,我們開發的時候,就無需關註 event 對象的部分兼容性問題。最典型的,如果我們要阻止默認事件,在 chrome 等瀏覽器中,我們可能要寫一個:

event.preventDefault();

而在 IE 中,我們則需要寫:

event.returnValue = false;

多虧了 jquery ,跨瀏覽器的實現,我們統一只需要寫:

event.preventDefault();

兼容?jquery 內部幫我們搞定了。類似的還有比如阻止事件冒泡以以及事件綁定(addEventListener / attachEvent)等,簡單到很多的後端都會使用 $(‘xxx‘).bind(...),這不是我們今天的重點,我們往下看。

(二)vue 中的 event 對象

我們知道,相比於 jquery,vue 的事件綁定可以顯得更加直觀和便捷,我們只需要在模板上添加一個 v-on 指令(還可以簡寫為 @),即可完成類似於 $(‘xxx‘).bind 的效果,少了一個利用選擇器查詢元素的操作。我們知道,jquery 中,event 對象會被默認當做實參傳入到處理函數中,如下:

$(‘body‘).bind(‘click‘, function (event) {
  console.log(typeof event);        // object 
});

這裏直接就獲取到了 event 對象,那麽問題來了,vue 中呢?

<div id="app">
    <button v-on:click="click">click me</button>
</div>
...
var app = new Vue({
    el: ‘#app‘,
    methods: {
        click(event) {
            console.log(typeof event);    // object
        }
    }
});

這裏的實現方式看起來和 jquery 是一致的啊,但是實際上,vue 比 jquery 要要復雜得多,jquery 官方也明確的說,v-on 不簡單是 addEventListener 的語法糖。在 jquery 中,我們傳入到 bind 方法中的回調,只能是一個函數表類型的變量或者一個匿名函數,傳遞的時候,還不能執行它(在後面加上一堆圓括號),否則就變成了取這一個函數的返回值作為事件回調。而我們知道,vue 的 v-on 指令接受的值可以是函數執行的形式,比如 v-on:click="click(233)" 。這裏我們可以傳遞任何需要傳遞的參數,甚至可以不傳遞參數:

<div id="app">
    <button v-on:click="click()">click me</button>
</div>
...
var app = new Vue({
    el: ‘#app‘,
    methods: {
        click(event) {
            console.log(typeof event);    // undefined
        }
    }
});

咦?我的 event 對象呢?怎麽不見了?打印看看 arguments.length 也是 0,說明這時候確實沒有實參被傳入進來。T_T,那我們如果既需要傳遞參數,又需要用到 event 對象,這個該怎麽辦呢?

(三)$event

翻看 vue 文檔,不難發現,其實我們可以通過將一個特殊變量 $event 傳入到回調中解決這個問題:

<div id="app">
    <button v-on:click="click($event, 233)">click me</button>
</div>
...
var app = new Vue({
    el: ‘#app‘,
    methods: {
        click(event, val) {
            console.log(typeof event);    // object
        }
    }
});

好吧,這樣看起來就正常了。
簡單總結來說:

  1. 使用不帶圓括號的形式,event 對象將被自動當做實參傳入;
  2. 使用帶圓括號的形式,我們需要使用 $event 變量顯式傳入 event 對象。

二、烏龍
前面都算是鋪墊吧,現在真正的烏龍來了。
翻看小夥伴兒的代碼,偶然看到了類似下面的代碼:

<div id="app">
    <button v-on:click="click(233)">click me</button>
</div>
...
var app = new Vue({
    el: ‘#app‘,
    methods: {
        click(val) {
            console.log(typeof event);    // object
        }
    }
});

看到這一段代碼,我的內心是崩潰的,丟進 chrome 裏面一跑,尼瑪還真可以,打印 arguments.length,也是正常的 1。尼瑪!這是什麽鬼?毀三觀啊?
既沒有傳入實參,也沒有接收的形參,這個 event 對象的來源,要麽是上級作用鏈,要麽。。。是全局作用域。。。全局的,不禁想到了 window.event
。再次上 MDN 確認了一下,果然,window.event,ie 和 chrome 都在 window 對象上有這樣一個屬性:

技術分享圖片 window.event

代碼丟進 Firefox 中運行,event 果然就變成了 undefined 了。額,這個我也不知道說什麽了。。。



作者:江湖z
鏈接:https://www.jianshu.com/p/b078cfe97c92
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。

vue.js - 奇怪的 event 對象