JavaScript:transitionend 事件的折腾

2016-11-23 1212 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';

本站文章均为深正网站建设摘自权威资料,书籍,或网络原创文章,如有版权纠纷或者违规问题,请即刻联系我们删除,我们欢迎您分享,引用和转载,但谢绝直接搬砖和抄袭!感谢...
关注深正互联