JavaScript:transitionend 事件的折騰

2016-11-23 1499 0 編輯:網頁程序開發永勝 來源:程序設計書籍

1、引子

JavaScript

var $demo = document.getElementById('demo');

    $demo.onclick = function () {

        alert(1);

    };

    $demo.addEventListener('click', function () {

        alert(2);

    });

HTML

<div id="demo" style="width:100px;height:100px;background:#eee;"></div>

如上,單擊方塊的運行結果應該是什么呢?在高級瀏覽器下測試的結果是:1、2,符合預期。

通常,dom元素上的事件名稱,比如“onclick、onmousedown”是與事件監聽的事件名稱是一一對應的,只是省略了“on”。于是:

JavaScript

var $demo = document.getElementById('demo');


$demo.onclick = function () {

    $demo.style.width = '200px';

    $demo.style.transition = 'all 2s';

};

$demo.ontransitionend = function () {

    $demo.innerHTML = 'done';

};


$demo.addEventListener('transitionend', function () {

    $demo.style.backgroundColor = '#fcc';

});

HTML

<div id="demo" style="width:100px;height:100px;background:#eee;"></div>

如上,ontransitionend 是監聽 css3 中 transition 過渡結束的事件,相關鏈接可以閱讀參考鏈接。實際運行結果是,#demo 元素內并未如期的出現 done 內容。


2、折騰

于是嘗試用駝峰形式來書寫,如 onTransitionEnd、onWebkitTransitionEnd 都沒有達到預期的結果。為什么要做這個嘗試?因為有這樣的事件名稱:DOMContentLoaded。并且,奇葩的是,這個事件名稱雖然是監聽 document 的,但是也無法使用 document.onDOMContentLoaded 來監聽。但 "onDOMContentLoaded" in document 卻返回 true,讓人摸不著頭腦。

因此,嘗試使用 in 操作符來檢測元素是否含有該事件監聽方法存在。

"onDOMContentLoaded" in document; // => true

"ontransitionend" in document.body; // => false

"onTransitionEnd" in document.body; // => false

"onWebkitTransitionEnd" in document.body; // => false

上面結果的出現,倍感吃驚。當我們嘗試在 window 對象上進行 in 檢測時:

"ontransitionend" in window; // => true

真調皮的。當我拿著這段欣喜若狂的代碼去火狐下檢測時:

"ontransitionend" in window; // => false

"ontransitionend" in document;; // => false

"ontransitionend" in document.body;; // => false

"onMozTransitionEnd" in window;; // => false

"onMozTransitionEnd" in document;; // => false

"onMozTransitionEnd" in document.body;; // => false

火狐更讓我吃驚。但是火狐確實可以用 document.addEventListener 來監聽到 transitionend 事件的,卻無法檢測出來。

于是,找來了 zepto 這個腳本庫來參考,才出這么一個蹩腳的檢測方案:

先檢測 transition-property 這個 css 屬性的私有前綴,然后添加到 transitionend 前面去(詳細方法見下一節)。確實可以這樣檢測,但多多少少讓人覺得有些失真,css 屬性的私有前綴和 JS 事件的私有前綴,雖然有聯系,但他們是沒有交集的。比如瀏覽器率先支持了css3 的標準屬性,但有私有前綴,但并不能說明,此時瀏覽器已經支持該 css3 的事件結束回調!?

不過怎樣吧,這也算是繞了彎路,多少都已經到達目的地了。


3、私有前綴檢測工具

3.1、檢測 css3 私有前綴

/**

 * 獲取有瀏覽器前綴的CSS3名稱

 * @param {String} standard 標準的CSS3屬性

 * @returns {String|null} 私有CSS3屬性

 *

 * @example

 * compatible.css3('border-start');

 * // => "-webkit-border-start"

 */

css3: function (standard) {

    var cssKey = null;

    var find = !1;

    standard = _toSepString(standard.trim().replace(regCss3, ''));

    dato.each(css3Prefixs, function (index, prefix) {

        cssKey = prefix ? prefix + '-' + standard : standard;

        var testCssKey = fixCss[cssKey] ? fixCss[cssKey]: cssKey;

        if (_toHumbString(testCssKey) in p.style) {

            find = !0;

            return !1;

        }

    });

    return find ? cssKey : null;

}

原理很簡單,遍歷一下私有前綴 ['', '-webkit', '-moz', '-ms'],使用 in 操作符在 style 對象里進行匹配,返回最先匹配到的,否則返回 null。

3.2、檢測 html5 私有前綴

/**

 * 獲取有瀏覽器前綴的方法名稱

 * @param {String} standard 標準屬性、方法名稱

 * @param {Object} parent   標準方法父級

 * @param {Boolean} [isEventType=false]   是否為事件類型

 * @returns {String} 私有屬性、方法名稱

 *

 * @example

 * compatible.html5('audioContext', window);

 * // => "webkitAudioContext"

 */

html5: function (standard, parent, isEventType) {

    var html5Key = null;

    var find = !1;

 

    if(isEventType){

        standard = standard.replace(regOn, '');

    }

 

    dato.each(html5Prefixs, function (index, prefix) {

        html5Key = isEventType ?

            (prefix + standard ):

            (prefix ? prefix + _toUpperCaseFirstLetter(standard) : standard);

 

        if ((isEventType ? 'on':'') + html5Key in parent) {

            find = !0;

            return !1;

        }

    });

 

    return find ? html5Key : undefined;

}

html5 檢測要稍微多做一步,需要指定父級對象和是否為事件名稱(事件名稱都帶有 on 前綴)。原理也很簡單,也是遍歷 ['', 'webkit', 'moz', 'ms', 'MS'] 操作。

最后,檢測出 transitionend 的私有方法:

var css = 'transition-property';

var transitionendEventPrefix = compatible.css3(css).replace(css, '').replace(/-/g, '');

var transitionendEventType = transitionendEventPrefix ? transitionendEventPrefix + 'TransitionEnd' : 'transitionend';

本站文章均為深正網站建設摘自權威資料,書籍,或網絡原創文章,如有版權糾紛或者違規問題,請即刻聯系我們刪除,我們歡迎您分享,引用和轉載,但謝絕直接搬磚和抄襲!感謝...
關注深正互聯
七星彩头尾