简体   繁体   English

如何包装jQuery函数

[英]How to wrap the jQuery function

Question

I'd like to know the best way I can wrap the jQuery function while retaining all functionality. 我想知道在保留所有功能的同时包装jQuery函数的最佳方法。 Essentially I want to call $('#someId') but have it operate as $('#' + id + 'someId') by wrapping the function, modifying the arguments, and passing it through to the original jQuery function. 本质上我想调用$('#someId')但是它通过包装函数,修改参数并将其传递给原始jQuery函数来操作$('#' + id + 'someId')

Motivation 动机

I have a section of JS that will reuse the same variable winId which is concatenated and passed to jQuery. 我有一节JS将重用相同的变量winId ,它连接并传递给jQuery。 Instead of writing 而不是写作

$('#' + winId + 'someId').html();
$('#' + winId + 'someOtherId').css();
...
$('#' + winId + 'someThirdId').text();

throughout the whole file, I want to wrap the jQuery function so I can just call 整个文件,我想包装jQuery函数,所以我可以调用

$('#someId').html();
$('#someOtherId').css();
...
$('#someThirdId').text();

and and have winId added in before passing through to $ . 并且在通过$之前添加了winId


My attempt 我的尝试

Here's what I'm thinking as a wrapper: 这就是我作为包装器的想法:

(function() {
    var fn = $;

    return $ = function() {
       for ( var i = 0; i < arguments.length; i++ ) {
          if ( typeof arguments[i] == 'string') {
             arguments[i] = /* code to add in winId, omitted */
          }
       }
       return fn.apply( this, arguments );
    }
})();

This works great, except that obviously none of the methods like $.ajax are available: 这很好用,除了显然没有像$.ajax这样的方法可用:

Uncaught TypeError: Object function () {
    for ( var i = 0; i < arguments.length; i++ ) {
       if ( typeof arguments[i] == 'string' ) {
          arguments[i] = /* code to add in winId, omitted */
       }
    }
    return fn.apply( this, arguments );
} has no method 'ajax' 

Note: I know I could copy the object over using jQuery.extend($, jQuery) , but I'm interested in a more elegant solution than that if possible. 注意:我知道我可以使用jQuery.extend($, jQuery)复制对象,但是我对一个更优雅的解决方案感兴趣,如果可能的话。

Here's a different implementation: 这是一个不同的实现:

DEMO DEMO

(jQuery.fn.init = (function (init) {

    return function (selector) {
        if (typeof selector === 'string' && selector[0] === '#') {
            arguments[0] = selector.replace('#', '#prefix_');
        }

        return init.apply(this, arguments);
    };

})(jQuery.fn.init)).prototype = jQuery.fn;


$(function () {
    console.log($('#test').length);
    console.log($.ajax);
});

EDIT: Followup question: How can I apply this only within a closure? 编辑:后续问题:我怎样才能在闭包中应用它? For example, within an object. 例如,在一个对象中。

Perhaps with functions that allows to add named decorators and remove them, something like: 也许使用允许添加命名装饰器并删除它们的函数,例如:

HTML HTML

<div id="prefix_test"></div>

JS JS

var decJQ = (function (decJQ, $) {
    var decorators = {},
        init = $.fn.init;

    ($.fn.init = function () {

        for (var k in decorators) {
            if (decorators.hasOwnProperty(k)) {
                arguments = decorators[k].apply(this, arguments);
            }
        }

        return init.apply(this, arguments);
    }).prototype = $.fn;

    return $.extend(decJQ, {
        decorate: function (name, fn) {
            decorators[name] = fn;
        },
        undecorate: function (name) {
            delete decorators[name];
        }
    });

})(window.decJQ || {}, jQuery);

decJQ.decorate('idPrefix', function (selector) {
    if (typeof selector === 'string' && selector[0] === '#') {
        arguments[0] = selector.replace('#', '#prefix_');
    }

    return arguments;
});

$(function () {
    console.log($('#test').length); //1

    decJQ.undecorate('idPrefix');

    console.log($('#test').length); //0
});

EDIT 2: You could also go for something extremely simple, such as: 编辑2:你也可以选择一些非常简单的东西,例如:

(function ($) {
    //use $ which has been wrapped
})(function () {
    //do some manipulations
    return jQuery.apply(this, arguments);
});

Following the suggestion by Bergi and the post he links to here , this is one way to go: 按照Bergi的建议和他链接到这里的帖子,这是一种方法:

$.fn.extend({
    initCore: $.fn.init,
    init: function (selector, context, rootjQuery) {
        if (typeof selector === 'string' && selector[0] === '#') {
            selector = selector.replace('#', '#' + winId);
        }
        return $.fn.initCore(selector, context, rootjQuery);
    }
});

$.fn.init.prototype = $.fn;

I've tested $('#foo') will find a div that has a winId prefixed to the id value, like this <div id="1foo"></div> . 我测试过$('#foo')会找到一个以id值为前缀的winId的div,就像这个<div id="1foo"></div>

For example: http://jsfiddle.net/MfdJS/1/ 例如: http//jsfiddle.net/MfdJS/1/

Add class="winID" to your elements. 将class =“winID”添加到元素中。

Use $(".winID").find('#someId").css(...) to access CSS attributes of specific element. 使用$(“。winID”)。find('#someId“)。css(...)来访问特定元素的CSS属性。

Use $(".winID").css(...) to access CSS attribues to all winID tagged elements. 使用$(“。winID”)。css(...)来访问所有winID标记元素的CSS属性。

ok well i just tested 好吧,我刚刚测试过

$('.con'+'tainer')

and

$('d'+'iv');

and

var s = 't';
$('.con'+s+'ainer');

and the console is returning the correct values 并且控制台返回正确的值

i belive that you are calling a function jQuery() with a string parameter, so as long as you use the normal syntax for building/appending/constructing a string with the plus signs, i think you're golden. 我相信你正在使用字符串参数调用函数jQuery(),所以只要你使用普通语法来构建/附加/构造带有加号的字符串,我认为你是金色的。 im glad you asked this question because now i know too 我很高兴你问这个问题因为现在我也知道了

That's a pretty strange thing to do. 这是一件非常奇怪的事情。 Why don't you just create a CSS selector string for winId and save it as a variable? 为什么不为winId创建一个CSS选择器字符串并将其保存为变量?

var foo = '#' + winId;

Now you can do: 现在你可以这样做:

$(foo + ', #bar').html("add some content"); 

What you're proposing to do will leave any programmer working on this project -- including you six months from now -- completely flummoxed when they use $('#bar') and it's actually selecting #foo and #bar. 你提议做的事情将让任何程序员在这个项目上工作 - 包括你在六个月后 - 当他们使用$('#bar')并且实际上选择#foo和#bar时完全陷入困境。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM