【问题标题】:Javascript/jQuery Event Handler Scope inside object using keyword this使用关键字 this 的对象内部的 Javascript/jQuery 事件处理程序范围
【发布时间】:2016-04-07 13:29:35
【问题描述】:

我已经尝试了几天来解决这个问题。我已经阅读了很多关于 SO 的问题,并用谷歌搜索了很多不同的方式,并阅读/尝试了我发现的所有内容。到目前为止,我发现没有什么对我有用,我已经重写了我的代码一百万次,似乎尝试了不同的方法来做到这一点。

我觉得我在这里缺少一些非常明显的东西,也许只需要朝着正确的方向推动。如果我要解决这个完全错误的问题并且需要重组所有内容,我也可以这样做。

基本上我正在使用的是一个前端“控制器”,因为没有更好的词,它初始化一些变量,设置一些事件侦听器并响应用户操作。

我不在乎我是使用 jQuery 还是纯 JavaScript,我只想让它工作,即使我必须重新编写整个东西。我的目标是重负载下的速度和性能。我正在考虑的另一个选择是 node.js,但我在这方面的经验有限,所以希望用 jQuery 来解决这个问题。

当页面加载时,我没有收到错误消息,但是当我单击已设置事件侦听器的项目之一时,我收到错误消息...TypeError: Cannot Read Property 'apply' of undefined. 它指的是相应的行以var scope = this ? function(e)...开头

该行的目的是让this 关键字引用控制器对象,以便我可以从事件处理程序方法中调用对象方法。虽然看起来它可能没有按我的预期工作。

我尝试只使用.on 来设置单击和更改处理程序,但我也遇到了范围问题。再次感谢任何帮助。

(function ($) {
    $(function () {  //document ready

        function Controller(authId, authKey) {

            this.user.id = authId;
            this.user.key = authKey;

            this.init();
        };


        Controller.prototype = {

            eventChange: [ "amt", "multi" ],
            eventClick: [ "double", "half", "high", "low" ],

            event: { refresh: ['amt', 'multi'], update: ['double', 'half'], process: ['high', 'low'] },

            user: { id: '', key: '', name: '', balance: '' },

            init: function () {

                this.initEvents();
           },
            initEventz: function() {

                for (var i = 0; i < this.eventChange.length; i += 1) {

                    var ele = document.getElementById(this.eventChange[i]);

                    var scope = this ? function(e) { this.handleEvent.apply(this, ["change"]); } : this.handleEvent;

                    if(document.addEventListener) {
                        ele.addEventListener("change", scope, false);
                    } else if(document.attachEvent) {
                        ele.attachEvent("onchange",  scope);
                    }
                }

                for (var i = 0; i < this.eventClick.length; i += 1) {

                    var ele = document.getElementById(this.eventClick[i]);

                    var scope = this ? function(e) { this.handleEvent.apply(this, ["click"]); } : this.handleEvent;

                    if(document.addEventListener) {
                        ele.addEventListener("click", scope, false);
                    } else if(document.attachEvent) {
                        ele.attachEvent("onclick",  scope);
                    }  
                }
           },
           handleEvent: function (e) {

              var eventId = e.target.id;

              for (var event in this) {
                    if (this.hasOwnProperty(event)) {

                           console.log(event);
                    }
              }
          }
        };
       var Controller = new Controller($("#auth").val(), $("#key").val());


    }); //end document ready

})(jQuery);

【问题讨论】:

    标签: javascript jquery scope event-handling this


    【解决方案1】:

    您正在失去对此的引用。

    你可以用这段代码解决这个问题:

    var scope = this ? function(e) { this.handleEvent.apply(this, ["click"]); }.bind(this) : this.handleEvent;
    

    但如果您希望处理程序能够通过引用this 访问其范围内的元素,您应该这样写:

    var scope = this ? function(e) { this.handleEvent.apply(ele, ["click"]); }.bind(this) : this.handleEvent;
    

    或者这个

    var that = this;
    
    var scope = this ? function(e) { that.handleEvent.apply(ele, ["click"]); } : this.handleEvent;
    

    我看到了其他错误。因为如果thisundefined 那么scope 将是this.handleEvent 但这会引发错误,因为undefined 不能拥有handleEvent 属性。

    【讨论】:

    • 好的,我使用了您的第一个解决方案,通过使用 bind(this),但是现在当它到达 handleEvent 方法时,我收到错误,即尝试访问 e 时属性 'id' 未定义。目标.id。有什么想法吗?
    • 我可以看到您的代码在 codepen 或其他地方运行吗?我正在尝试修复它,但没有示例会更加困难。我将继续努力:)。我正在更改我的答案。
    • 是的,问题是当你使用 apply 时,第一个参数将是“上下文”,第二个参数是你想要传递给函数的参数数组,并且您将“click”作为handleEvent 的参数传递,并且您正在尝试读取字符串“click”的属性target.id
    • 试试这个var scope = this ? function(e) { this.handleEvent.call(this, e); }.bind(this) : this.handleEvent;
    • 这使得 e.target.id 在 handleEvent 方法中设置正确。但是,当我执行 for (var event in this) 时,事件未定义。有任何想法吗?我会标记正确并奖励赏金。但如果你能帮我弄清楚这个事件的事情,将不胜感激。仅供参考,我需要 2 天才能获得赏金,但我会的。如果您在几天内没有获得赏金,请在此处发表评论并提醒我。
    猜你喜欢
    • 2021-02-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 2015-11-28
    • 2011-08-09
    • 2011-10-23
    • 1970-01-01
    • 2012-12-14
    相关资源
    最近更新 更多