我正在处理这样一种情况,我需要将 jQuery 事件绑定(bind)到页面以处理通过 JSF 生成的 UI 更新。唉,JSF 糟透了,它会在所有内容上粘贴 onclick 事件,这抢占了我的任何 jQuery 工作。
感谢 SO 上的优秀人员,我找到了解决方案:
mixing my jQuery click events with existing object's onclick attribute
逻辑是:
- 在页面加载时,获取所有
onclick
属性并将它们存储在一个变量中。 - 绑定(bind)我的 jQuery 事件
- 在我自己的 jQuery 事件之后,我可以
eval
原始的 onclick:eval(onclickValueVariable)
这在我所有的虚拟 onclick 事件测试中都有效。
但随后它在该实时 JSF 页面上失败了。问题是所有 onclick 都以“return false”结尾,这会导致此错误:
return not in function
例如:
<div class="uglyJSFcreatedTag" onclick="console.log('hey');return false">
以及将触发它的 jQuery:
var $jsfTag = $('.uglyJSFcreatedTag');
var cacheOnclick = $jsfTag.attr(onclick);
$jsfTag.removeAttr('onclick');
...bunch of logic here to decide if the inline onclick should fire and, if so...
eval(cacheOnclick)
问题是 return false
。触发 eval 时似乎无法返回任何内容。
有解决办法吗?我想我可以将该值作为一个字符串并进行字符串解析以删除所有返回 false,然后从脚本本身调用它。但这听起来有点乱。有没有更优雅的解决方案?
如果不是,我应该在调用 eval
之前寻找过滤掉哪些特定的 JS 语句?
最佳答案
两种选择:
1. 使用您当前的方法,只需在对 onclick 字符串求值之前用一个函数对其进行包装。存储结果,并将其作为函数调用。确保使用适当的 this
上下文调用它:
var f = eval("(function(){ "+cacheOnclick+"})");
f.call($jsfTag[0]);
注意:函数声明周围的括号 ()
在 eval 中是必需的。这使得声明成为一个表达式(从句法上讲),从而使其在 eval 中合法。
2. 不要获取 onclick 属性,而是从 dom 元素本身获取实际功能。此外,除非您需要对代码中的 jsf 处理程序函数执行一些特殊操作,否则我建议您直接将 JSF 函数添加为 jquery 单击处理程序,而不是从代码中显式调用它:
var $jsfTag = $('.uglyJSFcreatedTag');
$jsfTag.bind('click', $jsfTag[0].onclick);
$jsfTag.removeAttr('onclick');
就我个人而言,我会选择方法 #2,但任何一种都应该有效。
更新:这是对选项 #2 的一点补充说明:
var $jsfTag = $('.uglyJSFcreatedTag');
这是来自您的示例——我们正在使用 jquery 检索一个集合,其中包含类名为“uglyJSFcreatedTag”的所有元素。
$jsfTag.bind('click', $jsfTag[0].onclick);
这会从集合 ($jsfTag[0]
) 中获取第一个元素,并获取该元素对象的 onclick
属性。 .onclick
是一个 javascript 属性,它包含对浏览器从“onclick”属性的字符串内容生成的已编译函数的引用。现在,因为我们有处理函数,我们可以使用 jquery bind()
function 将它直接绑定(bind)到 jquery click 事件。 .
$jsfTag.removeAttr('onclick');
最后,我们只删除属性。这没关系,因为我们已经通过 jquery 绑定(bind)了函数。如果我们不将其从“旧式”onclick 中删除,那么它将被调用两次。
注意:您可能已经注意到,上面的代码仅适用于所选集中的第一个元素。对于很可能您的集合包含多个元素的情况,您需要遍历集合并分别处理每个元素。以下是您将如何做到这一点:
var $jsfTag = $('.uglyJSFcreatedTag');
$jsfTag.each( function(idx, element) {
$(element).bind('click', element.onclick).removeAttr("onclick");
});
如果您想跳过某些元素的 jsf 处理程序,请在“每个循环”中插入逻辑来对此进行测试,并相应地跳过绑定(bind)调用。
如果您必须继续从点击处理程序中调用 jsf 处理程序,那么至少考虑使用 element.onclick
而不是 $(element)。属性('点击')
。后者需要eval,而前者不需要。
关于javascript - 在 JavaScript 中使用 `return false` 时处理 `eval`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7643379/