【发布时间】:2012-12-14 10:59:41
【问题描述】:
似乎 kendo 的 unobtrusive-javascript 样式事件在我的方法上下文中调用了 break this。
假设我有一个对象Foo,实例化为bar = new Foo()
function Foo(){};
Foo.prototype.name = "Herring";
Foo.prototype.doSomething = function(e) {
alert(this.name);
};
bar = new Foo();
例如使用数据点击附加事件
<a data-role="button" data-click="bar.doSomething">Click Me</a>
bar 的对象上下文被替换(不知道为什么,因为我们有方便的 element 容器。)所以 this.name 是未定义的。
我在对象构造函数中尝试了旧的var self = this;,但它不起作用,有谁知道解决这个问题的最佳方法是什么?
更新:Hacky 解决方法
因为我真的不想失去将模块包装为类的好处,所以我创建了事件调用函数包装器,然后调用相应对象的方法。
例如,将标记连接到包装函数。
<a data-role="button" data-click="doSomething">Click Me</a>
而包装函数只是调用 object.method。
function doSomething(e){ bar.doSomething(e) };
现在,这达到了预期的结果,但它非常可怕,从标记调用的每个事件都必须有一个代理函数,就像上面的那个。所以想象一下你有 300 个事件的场景......你会立即明白为什么这是可怕的。
如果没有其他解决方案,我非常希望有。我将发布此解决方法作为答案,但就我而言,它远非理想。
脚注
老实说,这似乎是 Kendo 的主要架构缺陷,因为这种从标记调用事件的方法是“剑道方式”。显然它不能被修补,因为可能已经有相当多的代码已经处理this 作为对 html 元素的引用。
能够覆盖它,或者能够通过通用处理程序路由这些事件调用,该处理程序可以传递调用,本质上是通用代理函数,是可能的处理方式。它也可以是 kendo. 对象上的一个简单可配置值。
理论解
如果可行,我将发布后续跟进,理论上可以在通用代理上引发事件,并让它调用适当范围的函数。
假设我们使用事件属性来调用代理,然后创建一个单独的属性来传达对象/方法调用。例如。
<a data-role="button" data-click="prox" data-prox="o.eventHandler">Click Me</a>
代理函数将从属性数据集中提取prox:
方法 - 使用 eval
不是因为我是邪恶的,而是必须的。
// sitting in global namespace
function prox(e){
var p = e.sender.element.data['prox'];
// make sure our delegate is a function.
if("function" == eval("typeof "+p)) {
eval(p + "(e)");
}
}
显然我想要一个更好的方法来做到这一点,但至少它是干燥的。
(一会儿我会做一个非 eval 方法...)
开始评估...
让我们使用窗口上下文来定位对象/方法。
function prox(e) {
var p = e.sender.element.data['prox'];
if(p.indexOf(".") == -1){
// global function : where *this* is window.
// check you've got the function if not ditch it.
if("function" == typeof window[p]) window[p](e);
} else {
// object/method (one level deep only.)
var s = p.split(".");
var o = s[0], m = s[1];
// check the object/method is a function before executing it.
if("function" == typeof window[o][p]) window[o][p](e);
}
}
当然对于全局(窗口)范围的函数,this 作为元素可能更有用,但在这种情况下,你可以选择,我会省略
【问题讨论】:
标签: javascript this kendo-ui unobtrusive-javascript