jQuery noConflict不工作

时间:2012-08-16 10:48:34

标签: javascript jquery

我有以下的JavaScript,它将从客户的网站上引用。它使用jQuery 1.5所以我的问题是如果客户端已经加载了jQuery的实例?或者另一种JavaScript库?

我正在使用noConflict()尝试解决这个问题,但它似乎无法正常工作,我无法解决原因。任何帮助表示赞赏

主要问题是我收到一条错误,告诉我jQueryMH未定义,但在我甚至在keepAlive函数上设置间隔之前我已经明确定义了它。

var head    = document.getElementsByTagName('head')[0];
var script  = document.createElement('script');
script.src  = '//ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js';
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function() {
                                                var jQueryMH = jQuery.noConflict(true);
                                                setInterval(keepAlive(), 5000);
                                            };
head.appendChild(script);
function keepAlive() {
    var mhProtocol      = ((document.location.protocol == "https:") ? "https://" : "http://");
    var randomNumber    = Math.floor(Math.random()*10000);
    var mhVisitorId     = document.cookie.match('mhVisitorId=(.*?)(;|$)');
    var urlParamString  = "";
    if(mhVisitorId) { 
        urlParamString = "&mhVisitorId=" + encodeURIComponent(mhVisitorId[1]); 
    }
    var mhUrl = "www.urlishere.com";
    //var jQueryMH = jQuery.noConflict();
    jQueryMH.ajax({
        url: mhUrl,
        dataType: 'jsonp'
    });
}

除此之外,我已经尝试在函数本身中设置noConflict()并且这可以工作并允许我引用jQueryMH,但是我们有以下问题,可能是因为它每次运行函数时都设置noConflict(每个5S)

我设置的测试页面外部包含这个JS脚本已经加载了jQuery 1.8,然后它加载了上面的脚本。因为我的noConflict,我希望jQueryMH.fn.jquery返回1.5.0,jQuery.fn.jquery返回1.8;然而它们都返回1.5.0,这意味着我的noConflict无效,因为jQuery没有保留,因为已经加载到客户网站上的1.8版本库。

3 个答案:

答案 0 :(得分:1)

在加载第二个版本之前,您实际上需要noconflict 第一个版本的jQuery,否则第二个版本将覆盖第一个版本。

除此之外,您的未定义变量问题是由于您在函数内调用.noconflict并将jQuery分配给仅在该函数范围内的范围内的备用变量而引起的。< / p>

我认为你需要先做:

var origjQuery = jQuery.noconflict();

然后像上面那样加载新的jQuery,然后加载noconflict

var jQueryMH = jQuery.noconflict();

然后恢复原始jQuery:

var jQuery = origjQuery.noconflict();

在全球范围内完成上述所有工作。

答案 1 :(得分:1)

我构建了一个jQuery的自定义构建,修改了将jQuery分配给全局变量的代码行。

具体来说,我改变了以下代码:

window.jQuery = window.$ = jQuery;

window.myCustomJquery = jQuery;

通过这种方式,即使在页面中包含jQuery脚本,我也可以毫无问题地注入我自定义的jQuery构建,而无需密封/冻结实际的全局jQuery或不使用.noConflict(),两种解决方案导致上述问题的原因。

答案 2 :(得分:0)

在任何其他主机上注入脚本时,我确实遇到了这个问题。

正如Alnitak所说,noConflict如果先加载jQuery,然后覆盖$变量,而不是相反,则可以正常工作。

我设法构建的解决方法使用ECMAScript 5中的Object.freezeObject.seal方法。

问题是将要覆盖现有网站的变量(例如$)复制到最终会冻结的对象中。
通过在重写变量之前冻结该对象(在加载jQuery之前),确保原始变量的副本(在您的情况下为$)将存储在您的对象中,并且它们不能以任何方式被任何方式更改其他剧本。
加载所需的库后,您只需将已冻结的对象属性复制回全局对象,保持主机环境不变。
这是一个使事情更清晰的示例代码:

var aux = {'jQuery' : window.jQuery};
if(Object.freeze)
    // prevent anyone from deleting any of the `aux` props
    Object.freeze(aux);
if(Object.seal)
    // prevent anyone from altering the initial jQuery
    // this is necessary because `aux.jQuery` is a copy by reference of the
    // window.jQuery, thus any modification in the global jQuery object
    // would be reflected in our jQuery copy
    Object.seal(aux.jQuery);

var head    = document.getElementsByTagName('head')[0];
var script  = document.createElement('script');
script.src  = '//ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js';
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function() {
    var jQueryMH = jQuery.noConflict(true);
    // restore the initial jquery
    window.jQuery = aux.jQuery;
    alert(jQuery === jQueryMH);
};

当然,您可以扩展功能并将其用于您使用的任何其他库:

var __globalLibs = {},
    libsThatYouWantToPreserve = '$ jQuery otherLib'.split(' '),
    key;

for(var i=0,l=libsThatYouWantToPreserve.length;i<l;i++)
    {
        key = libsThatYouWantToPreserve[i];
        // copy the contents of the global variable into your object
        __globalLibs[key] = window[key];
        if(Object.seal)
            Object.seal(__globalLibs[key]);
    }

if(Object.freeze)
    Object.freeze(__globalLibs);

// load jquery and all the other libs

// make copies of your update libs

var jQueryMH = jQuery;

// and then restore the initial variables to the global context
 for(var i=0,l=libsThatYouWantToPreserve.length;i<l;i++)
    {
        key = libsThatYouWantToPreserve[i];
        // copy the contents of the global variable into your object
        window[key] = __globalLibs[key];
    }

// after that, you can just delete your object
delete window.__globalLibs; 

唯一的缺点是IE8和更低版本不支持 希望这可以帮助!

P.S。 :您应该将setInterval(keepAlive(), 5000);更改为setInterval(keepAlive, 5000);,因为您的构造意味着重复评估keepAlive 返回值undefined) - 而不是功能本身 - 每5秒钟。