javascript - KendoUI 数据属性事件处理程序和 'this' 范围

标签 javascript this kendo-ui unobtrusive-javascript

似乎 kendo 的 unobtrusive-javascript 风格的事件调用在我的方法上下文中打破了 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 中的主要架构缺陷,因为这种从标记调用事件的方法是“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 作为元素可能更有用,但在那种情况下,您可以选择,我将省略

最佳答案

正在使用的版本。

// dynamic proxy for retaining object context on methods called by
// data- attributes in Kendo.
// 
// e.g.
//
//     data-click="o.method" 
//
// Would lose context with `o` - context would be set in the same
// way as JQuery handlers, which is an inconvenience.
// 
// Alternatively we use the prox method
//
//     data-click="prox"
// 
// We'd then set `data-prox` on the same element, to the
// object.method pair.
//
//     data-prox="o.method"
//
// This is read by prox, transformed into a method call, type
// checked and executed if it's a valid method.
//
// A `data-prox` value in any form other than `object.method` will
// be ignored, for example, `object.child.method` will fail. If
// you're doing that sort of thing, feel free to hack it.
// 
// There's a backup eval() to locate the object if window doesn't
// own it. It should be possible to remove it under most
// circumstances, it's here for compatability with
// JSFiddle. (JSBin works without it.)
function prox(e) {
    var p = this.element.data().prox;
    if(p.indexOf(".") > -1){
        var s = p.split("."); if(s.length > 2) return; 
        var o = s[0], m = s[1];
        if("object" == typeof window[o]) {
            o = window[o];
        } 
        if("function" == typeof o[m]) o[m](e);
        // comment this out in production:
        l( "prox called " + s[0] + "::" + s[1] );
    }
}

function l(s) { console.log(s); }

注意事项

如果你在同一个元素上有多个处理程序,prox() 是不合适的,例如,如果你有data-initdata-show 等。prox 无法区分,将失败。

我可能会对此进行更新,尤其是当这对我来说成为一个普遍的用例时。

关于javascript - KendoUI 数据属性事件处理程序和 'this' 范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14082034/

相关文章:

kendo-ui - Kendo Treeview ,过滤项目

javascript - 使用带有 "Read More"和 "Read Less"的 JavaScript chop 文本

将鼠标悬停在 Javascript 文本框上

java - 将 "this"关键字与构造函数一起使用 - "this"如何引用 Point 对象?

Javascript:将 OOP 方法附加到事件和 'this' 关键字

javascript - 内部魔镜警报功能

javascript - Kendo 网格 - 如何在添加/编辑子行(详细信息网格)时访问父行模型

javascript - 如何使用@media 只加载一个 IFRAME 并显示 :none; CSS

javascript - 我无法弄清楚为什么弹出窗口会在出现错误或发送时消失并重新出现

angularjs - KendoGrid 使用选中的复选框而不突出显示行