问题
我想知道在保留所有功能的同时包装jQuery函数的最佳方法。本质上我想调用$('#someId')
,但通过包装函数,修改参数并将其传递给原始jQuery函数,使其作为$('#' + id + 'someId')
运行。
动机
我有一段JS将重用相同的变量winId
,它连接并传递给jQuery。而不是写
$('#' + winId + 'someId').html();
$('#' + winId + 'someOtherId').css();
...
$('#' + winId + 'someThirdId').text();
在整个文件中,我想包装jQuery函数,所以我可以调用
$('#someId').html();
$('#someOtherId').css();
...
$('#someThirdId').text();
并且在传递给winId
之前添加了$
。
我的尝试
以下是我作为包装器的想法:
(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 );
}
})();
这很有效,但显然没有像$.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'
注意:我知道我可以使用jQuery.extend($, jQuery)
复制对象,但我对比这更好的解决方案感兴趣。
答案 0 :(得分:4)
这是一个不同的实现:
(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);
});
编辑:后续问题:如何才能在闭包中应用此功能?例如,在对象中。
可能使用允许添加命名修饰符并删除它们的函数,例如:
HTML
<div id="prefix_test"></div>
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
});
编辑2: 你也可以选择一些非常简单的东西,例如:
(function ($) {
//use $ which has been wrapped
})(function () {
//do some manipulations
return jQuery.apply(this, arguments);
});
答案 1 :(得分:2)
根据Bergi的建议以及他链接到here的帖子,这是一种方法:
$.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;
我已经测试过$('#foo')
会找到一个以winId
为前缀id
的div,就像这个<div id="1foo"></div>
一样。
答案 2 :(得分:1)
将class =“winID”添加到元素中。
使用$(“。winID”)。find('#someId“)。css(...)来访问特定元素的CSS属性。
使用$(“。winID”)。css(...)来访问所有winID标记元素的CSS属性。
答案 3 :(得分:-1)
好吧,我刚刚测试了
$('.con'+'tainer')
和
$('d'+'iv');
和
var s = 't';
$('.con'+s+'ainer');
并且控制台返回正确的值
我相信您正在使用字符串参数调用函数jQuery(),因此只要您使用正常语法构建/附加/构造带有加号的字符串,我认为您是金色的。我很高兴你问这个问题,因为现在我也知道了
答案 4 :(得分:-2)
这是一件非常奇怪的事情。为什么不为winId创建一个CSS选择器字符串并将其另存为变量?
var foo = '#' + winId;
现在你可以做到:
$(foo + ', #bar').html("add some content");
你提出要做的事情将让任何程序员在这个项目上工作 - 包括你在六个月之后 - 当他们使用$('#bar')并且它实际上选择#foo和#bar时完全陷入困境。