轻松搞定jQuery.noConflict()


Posted in Javascript onFebruary 15, 2016

jQuery是目前使用最广泛的前端框架之一,有大量的第三方库和插件基于它开发。为了避免全局命名空间污染,jQuery提供了jQuery.noConflict()方法解决变量冲突。这个方法,毫无疑问,非常有效。遗憾的是,jQuery的官方文档对该方法的描述不够清晰,许多开发者并不清楚当他们调用jQuery.noConflict()时,究竟发生了什么,从而导致在使用时出现了许多问题。尽管如此,jQuery.noConflict()背后实现原理依然值得Web开发者学习掌握,成为解决类似全局命名空间污染问题的利器。

jQuery.noConflict()的作用?
  jQuery.noConflict()的存在只有一个目的:它允许你在同一个页面加载多个jQuery实例,尤其是不同版本的jQuery。你可能会觉得奇怪,为什么要在一个页面加载/使用多个不同版本的jQuery对象呢?一般而言,有两种情况。第一种情况,你的业务代码采用了最新版的jQuery库,而你选用的第三方插件依赖的更早版本的jQuery库;第二种情况,你正维护着一个系统,它已有的业务代码由于各种原因,引用了较老版本的jQuery库,你新开发的模块采用的是其他版本的jQuery库。不论哪种情况,你都不得不面对,jQuery对象/方法冲突的问题。幸运的是,jQuery.noConflict()帮你解决了这个烦恼。

jQuery被加载时发生了什么?
  当jQuery被页面引用/加载时,它被封装在一个自执行函数(匿名函数)里,它提供的所有一切变量、函数、对象都在匿名函数内部的可执行环境内,外部环境无法调用,以防止全局命名空间污染。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

jQuery在匿名函数内部定义了两个全局对象:jQuery和$,把自己暴露给外部环境。开发者习惯使用的各种公共方法都是通过这两个对象进行访问的,如jQuery.ajax(),jQuery.css()等。在最初,它们指向匿名函数内部的同一个对象jQuery(私有变量),通过它访问匿名函数内部的私有变量和函数。这使得匿名函数在自执行后其内部的私有变量和函数仍然进驻在内存里,不会被javascript的垃圾回收机制清除。

window.jQuery = window.$ = jQuery;

  当jQuery被页面加载后,当前页面有可能已经存在了jQuery和$这两个全局变量(比如,加载了其它的第三方库,其内部也定义了它俩),这就会导致已经存在的对象被覆盖(全局命名空间污染)。为了解决这个问题,jQuery在内部先将已经存在的全局变量缓存起来,保存在私有变量_jQuery和_$中,供后续调用。所以,如果页面在加载jQuery库时,还不存在jQuery和$对象,那么_jQuery和_$都是undefined;否则,它们都会保存对已有jQuery和$的引用(也许来自之前引用的第三方库或是不同版本的jQuery库)。之后,jQuery会像上文说描述的那样,覆盖这两个全局变量并将自己暴露给外部环境。至此,页面上的全局变量jQuery和$已经指向刚刚引入的jQuery库。

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

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

// Otherwise expose jQuery to the global object as usual
window.jQuery = window.$ = jQuery;

jQuery.noConflict()的神奇效果?
  假设你维护的系统已经引用了1.7.0版本的jQuery库,而你在新添加的功能里引用了1.10.2版本的jQuery库。那么,还有办法重新使用jQuery 1.7.0 或是同时使用两个版本的jQuery库吗?答案是肯定,那就是jQuery.noConflict()。实际上,利用jQuery.noConflict(),你可以立刻把全局变量jQuery和$重新指向之前引用的对象。很神奇吧?这就是为什么jQuery在对外暴露自己前内部缓存了之前引用的对象。
  jQuery.noConflict()接受一个可选的布尔值参数,通常默认值是false。这个参数会带来什么影响呢?其实,很简单。如果调用jQuery.noConflict()或是jQuery.noConflict(false),只有全局变量$会被重置恢复成之前的引用值;如果调用jQuery.noConflict()或是jQuery.noConflict(true),那么全局变量jQuery和$都会被重置恢复成之前的引用值。这一点非常重要,建议牢记。当你调用jQuery.noConflict(false/true)之后,它会返回当前jQuery的实例,利用这个特性我们可以实现jQuery的重命名。

// "Renaming" jQuery
var jayquery = jQuery.noConflict( true );
// Now we can call things like jayquery.ajax(), jayquery.css(), and so on

我们再来看一个代码片段,测试一下是否真正理解了神奇的noConflict()

<!-- jQuery and $ are undefined -->

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- jQuery and $ now point to jQuery 1.10.2 -->

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js">
<!-- jQuery and $ now point to jQuery 1.7.0 -->

<script>jQuery.noConflict();</script>
<!-- jQuery still points to jQuery 1.7.0; $ now points to jQuery 1.10.2 -->

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js">
<!-- jQuery and $ now point to jQuery 1.6.4 -->

<script>var jquery164 = jQuery.noConflict( true );</script>
<!-- jQuery now points to jQuery 1.7.0; $ now points to jQuery 1.10.2; jquery164 points to jQuery 1.6.4 -->

避免第三方库的冲突
  以上的代码片段展示了如何解决多版本jQuery的冲突。接下来,我们尝试解决jQuery库和第三方库的冲突,下面出现的代码片段在jQuery的官方文档中都有,有兴趣的程序猿可以仔细阅读官方文档体会其中的区别。

1、直接使用No-Conflict模式
  使用No-Conflict模式,其实就是对jQuery进行重命名,再调用。

<!-- 采用no-conflict模式,jquery.js在prototype.js之后被引入. -->
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script>
 
var $j = jQuery.noConflict();
// $j 引用了jQuery对象本身.
 
$j(document).ready(function() {
  $j( "div" ).hide();
});
 
// $ 被重新指向prototype.js里定义的对象
// document.getElementById(). mainDiv below is a DOM element, not a jQuery object.
window.onload = function() {
  var mainDiv = $( "main" );
}
 
</script>

2、使用自执行函数封装
  使用这种方式,你可以在匿名函数内部继续使用标准的$对象,这也是众多jQuery插件采用的方法。需要注意的是,使用这种方法,函数内部无法再使用prototype.js定义的$对象了。

<!-- jquery.js在prototype.js之后被引入. -->
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script>
 
jQuery.noConflict();
 
(function( $ ) {
  // Your jQuery code here, using the $
})( jQuery );
 
</script>

3、使用标准jQuery(document).ready()函数
  如果jQuery库在其它库之前引入,那么jQuery内部定义的jQuery和$会被第三方库覆盖,这时候再使用noConflict()已经没有什么意义了。解决的方法很简单,直接使用jQuery的标准调用方式。

<!-- jquery.js在prototype.js之前被引入. -->
<script src="jquery.js"></script>
<script src="prototype.js"></script>
<script>
 
// Use full jQuery function name to reference jQuery.
jQuery( document ).ready(function() {
  jQuery( "div" ).hide();
});

// 或者
jQuery(function($){
  // Your jQuery code here, using the $
});
 
// Use the $ variable as defined in prototype.js
window.onload = function() {
  var mainDiv = $( "main" );
};

</script>

以上就是为大家介绍的jQuery.noConflict()使用方法,希望大家分分钟可以玩转jQuery.noConflict()。

Javascript 相关文章推荐
jquery对象和DOM对象的区别介绍
Aug 09 Javascript
JS性能优化笔记搜索整理
Aug 21 Javascript
鼠标移到div,浮层显示明细,弹出层与div的上边距左边距重合(示例代码)
Dec 14 Javascript
Javascript WebSocket使用实例介绍(简明入门教程)
Apr 16 Javascript
js函数定时器实现定时读取系统实时连接数
Apr 30 Javascript
使用jQuery实现返回顶部
Jan 26 Javascript
JS+CSS实现下拉刷新/上拉加载插件
Mar 31 Javascript
React Native仿美团下拉菜单的实例代码
Aug 08 Javascript
javascript计算渐变颜色的实例
Sep 22 Javascript
详解Vue-cli中的静态资源管理(src/assets和static/的区别)
Jun 19 Javascript
推荐几个不错的console调试技巧实现
Dec 20 Javascript
小程序实现图片移动缩放效果
May 26 Javascript
JavaScript的Backbone.js框架的一些使用建议整理
Feb 14 #Javascript
简单了解Backbone.js的Model模型以及View视图的源码
Feb 14 #Javascript
Backbone.js框架中简单的View视图编写学习笔记
Feb 14 #Javascript
10个JavaScript中易犯小错误
Feb 14 #Javascript
讲解JavaScript的Backbone.js框架的MVC结构设计理念
Feb 14 #Javascript
深入解析JavaScript框架Backbone.js中的事件机制
Feb 14 #Javascript
Node.js 条形码识别程序构建思路详解
Feb 14 #Javascript
You might like
收音机术语解释
2021/03/01 无线电
PHP中数组的三种排序方法分享
2012/05/07 PHP
PHP数组传递是值传递而非引用传递概念纠正
2013/01/31 PHP
PHP更新购物车数量(表单部分/PHP处理部分)
2013/05/03 PHP
PHP实现从远程下载文件的方法
2015/03/12 PHP
PHP匿名函数和use子句用法实例
2016/03/16 PHP
CI框架AR操作(数组形式)实现插入多条sql数据的方法
2016/05/18 PHP
js控制表单操作的常用代码小结
2013/08/15 Javascript
js toFixed()方法的重写实现精度的统一
2014/03/06 Javascript
javascript读取Xml文件做一个二级联动菜单示例
2014/03/17 Javascript
window.setInterval()方法的定义和用法及offsetLeft与style.left的区别
2015/11/11 Javascript
jquery $.trim()去除字符串空格的实现方法【附图例】
2016/03/30 Javascript
BootStrap智能表单实战系列(六)表单编辑页面的数据绑定
2016/06/13 Javascript
jQuery插件Flexslider实现图片轮播、图文结合滑动切换效果
2020/04/16 Javascript
Vuex之理解Getters的用法实例
2017/04/19 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
2018/08/08 Javascript
jQuery设置下拉框显示与隐藏效果的方法分析
2019/09/15 jQuery
微信小程序tabBar设置实例解析
2019/11/14 Javascript
JS document文档的简单操作完整示例
2020/01/13 Javascript
vue 查看dist文件里的结构(多种方式)
2020/01/17 Javascript
[03:30]DOTA2完美“圣”典精彩集锦
2016/12/27 DOTA
Python列表list数组array用法实例解析
2014/10/28 Python
Python性能提升之延迟初始化
2016/12/04 Python
利用matplotlib+numpy绘制多种绘图的方法实例
2017/05/03 Python
python爬虫 爬取超清壁纸代码实例
2019/08/16 Python
python爬虫要用到的库总结
2020/07/28 Python
Python实现对word文档添加密码去除密码的示例代码
2020/12/29 Python
英国时尚女装购物网站:Missguided
2018/08/23 全球购物
英文版餐饮运营管理求职信
2013/11/06 职场文书
2014年教师节寄语
2014/04/03 职场文书
小学生手册家长评语
2014/04/16 职场文书
赡养老人协议书
2014/04/21 职场文书
中学生学雷锋演讲稿
2014/04/26 职场文书
运动会表扬稿范文
2015/05/05 职场文书
原生JS中应该禁止出现的写法
2021/05/05 Javascript
Jackson 反序列化时实现大小写不敏感设置
2021/06/29 Java/Android