jQuery的无冲突处理

2017-01-19

noConflict这个东西在prototype,mootools这些老古董基本都被淘汰的情况下,能用上的几率基本不大了,本身也是非常简单的东西,说白了就是别名替换。之所以在2017年还谈论这个东西是因为看到书上对这个东西的解释,完全是简单问题复杂化,把我看晕了,所以我看看自己想以最简单的方法把这个东西说清楚

背景

当你想在项目里加入一个库,这里拿Zepto和jQuery来举例,

如果项目原本没有使用过window.$,那么一切正常

但是如果项目是非常老的项目,你只知道引入了Zepto后,页面有些功能不正常了,当你去掉Zepto后就好了,然后你在console中打印$,发现$被使用了,具体它是个什么库你也不太清楚,如果想用上Zepto怎么办?

解决方法

显然,我需要在加载Zepto之前把window.$先保存起来,比如保存到变量_$中,然后加载Zepto后,window.$已经被赋值为Zepto了,这时重新给window.$赋上_$,然后用Zepto的时候,全局上就只能用别的名字,或者是把$写在闭包里,看下代码是怎样的

1
2
3
4
5
6
7
8
9
10
11
<script>
window.$ = _$; //确保_$在全局中并没有用到
</script>
<script src="//cdn.bootcss.com/zepto/1.2.0/zepto.js"></script>
<script>
window.$ = _$;

(function($) {
$('xxx'); // 在闭包里可以正常用$来表示Zepto
})(Zepto)
</script>

那么实际上这就是无冲突处理

jQuery的做法

因为Zepto出来的是为移动端服务,追求的是精简,肯定不希望你加两个库做一件事,所以Zepto库里并没有集成无冲突的处理

但jQuery不一样,jQuery那个年代,各种库都喜欢用$,所以jQuery在加载时都会先把window.$window.jQuery存起来,然后在给window.$window.jQuery赋上当前加载版本的jQuery,如果window.$在加载前已经被别的库使用了,那么jQuery提供了一个noConflict的方法,调用该方法即可把window.$还原回原来的

看看代码是怎么用的

1
2
3
4
5
6
7
8
9
10
<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.js"></script>
<script>
var jq = $.noConflict(); // 使用jq表示jQuery,释放$

// 或者
(function($) {
$('xxx'); // 在闭包里可以正常用$来表示jQuery
})($.noConflict());

</script>

以上示例仅替换了window.$

如果是想同时用两个版本的jQuery,比如先引入了1.x,然后有些地方想用2.x,那么在调用$.noConflict(true)即可同时替换window.$window.jQuery

看看jQuery源码

global.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var

// Map over jQuery in case of overwrite
_jQuery = window.jQuery,

// Map over the $ in case of overwrite
_$ = window.$;

jQuery.noConflict = function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}

if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}

return jQuery;
};

// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( !noGlobal ) {
window.jQuery = window.$ = jQuery;
}