我正在尝试编写一个JQuery插件来支持$ in元素id,我的代码是:
DollarSignPlugin.js:
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\\\$/g, "$");
return elementName.replace(/\$/g, "\\$");
}
var jQueryInit = $.fn.init;
$.fn.init = function(arg1, arg2, rootjQuery){
arg2 = arg2 || window.document;
if (arg1 && arg1.replace) {
var newArg1 = escapeJQueryElementName(arg1);
return new jQueryInit(newArg1, arg2, rootjQuery);
}
return new jQueryInit(arg1, arg2, rootjQuery);
};
它运作良好,但我遇到了当前行的一个问题:
var $anyselector = $("#");
JQuery抛出错误“语法错误,无法识别的表达式:#”。
当点击任何带有href =“#”的标签时,此行来自bootstrap。
删除插件时不会出现此错误,如果我将替换功能直接粘贴到jquery文件,它也可以正常工作。
那么是否有更好的方法来覆盖选择器,或者我的代码有问题,请帮忙吗?
答案 0 :(得分:3)
我强烈建议你不要这样做(但如果你愿意,继续阅读,我确实在下面做了修复),因为:
这意味着您在代码中使用了无效选择器,这是一个维护问题 - 在某些时候,进行维护的人将无法理解正在发生的事情,或者您将遇到边缘条件等。
您当前的实施会搞乱像
这样的事情$("<div>$12</div>").appendTo(document.body);
(在美元符号前加一个反斜杠)。谁知道还有什么搞砸?
相反,我只是有一个简单的:
function $gid(id) {
var e = document.getElementById(id);
if (!e) {
return $();
}
if (e.id === id) {
return $(e);
}
// Fallback processing for old IE that matches name attributes
return $('[id="' + id.replace(/"/g, '\\"') + '"]').filter(function() {
return this.id === id;
}).first();
}
示例:
// Plugin
function $gid(id) {
var e = document.getElementById(id);
if (!e) {
return $();
}
if (e.id === id) {
return $(e);
}
// Fallback processing for old IE that matches name attributes
return $('[id="' + id.replace(/"/g, '\\"') + '"]').filter(function() {
return this.id === id;
}).first();
}
// Use
$gid("a$b").css("color", "blue");
$gid("$c").css("color", "green");
<div id="a$b">a$b</div>
<div id="$c">$c</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
但是:如果你要这样做,你必须小心尽可能轻柔地踏上。这意味着调用具有完全相同数量的参数,相同this
值等的原始数据;并确保$.fn.init.prototype
与以前一样替换$.fn.init
后具有相同的值。
做这两件事似乎解决了这个问题:
// Plugin
(function () {
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\\\$/g, "$");
return elementName.replace(/\$/g, "\\$");
}
var slice = Array.prototype.slice;
var jQueryInit = $.fn.init;
$.fn.init = function (arg1) {
var args = slice.call(arguments, 0);
if (arg1 && arg1.replace) {
args[0] = escapeJQueryElementName(arg1);
}
return jQueryInit.apply(this, args);
};
$.fn.init.prototype = $.fn;
})();
// Use
$("#a$b").css("color", "blue"); // Using special version that handles $ without \\
$("#$c").css("color", "green"); // Using special version that handles $ without \\
$("<div>Checking '#' selector, should get 0: " + $("#").length + "</div>").appendTo(document.body);
<div id="a$b">a$b</div>
<div id="$c">$c</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
答案 1 :(得分:1)
一个更好的解决方案是一个能够创建jQuery的新别名并支持转义选择器的函数,而不是试图通过覆盖本应该只在内部使用的东西来解决这个问题。
顺便说一下,请记住,不应该对HTML内容进行转义,例如: $('<span>give me $$$</span>')
,所以我已经做了粗略的检查。
(function(jQuery) {
jQuery.withSelectorEscaping = function() {
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\\\$/g, "$");
return elementName.replace(/\$/g, "\\$");
}
return function(selector, context) {
// avoid doing this for HTML
if (selector && selector.replace && selector[0] !== '<') {
selector = escapeJQueryElementName(selector);
}
return jQuery(selector, context);
};
}
}(jQuery));
// create new alias here
$ = jQuery.withSelectorEscaping();
// use new alias
console.log($('#'));
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
此代码段向jQuery
本身添加了一个名为jQuery.withEscaping
的新功能;它会返回一个函数,然后您可以将其指定给您选择的别名,我在这里选择了$
,但您也可以这样做:
$foo = jQuery.withSelectorEscaping();
它只保留jQuery
本身的行为,只为需要它的事物公开你的转义功能。