【问题标题】:ES6 - How to access `this` element after binding `this` class?ES6 - 绑定`this`类后如何访问`this`元素?
【发布时间】:2016-11-26 06:32:50
【问题描述】:

绑定this类后如何访问this元素?

例如不绑定this:

$(".button-open").click(function(event) {
    console.log(this); // <a href="#" class="button-open">Open</a>
    this.openMe();
});

绑定this:

$(".button-open").click(function(event) {
   console.log(this); // Polygon {windowHeight: 965, scrollNum: 0}
   this.openMe();
}.bind(this));

绑定this后如何再次获取和访问&lt;a href="#" class="button-open"&gt;Open&lt;/a&gt;

完整代码:

class Polygon {
    constructor() {
        this.windowHeight = $(window).height();
        this.scrollNum = 0;
    }

    // Simple class instance methods using short-hand method
    // declaration
    init() {
        var clickMe = this.clickMe.bind(this);
        return clickMe();
    }

    clickMe() {
        $(".button-open").click(function(event) {
            console.log(this);
            this.openMe();
        }.bind(this));


        $(".button-close").click(function(event) {
            this.closeMe();
        }.bind(this));
    }

    openMe() {
        console.log(this.scrollNum); // 0
        this.scrollNum = 200;
        console.log(this.scrollNum); // 200
        return false;

    }

    closeMe() {
        console.log(this.scrollNum); // 200
        return false;
    }
}

export { Polygon as default}

有什么想法吗?

编辑:

同样的问题与 jQuery animate:

$(".element").animate({}, 'fast', 'swing', function(event) {
    console.log(this); // the element
}.bind(this));

绑定后:

$(".element").animate({}, 'fast', 'swing', function(event) {
    console.log(this); // undefined
}.bind(this));

任何全局或防弹方式再次获得element

【问题讨论】:

  • 我们不能通过 event.target 访问吗?
  • 再次使用jQuery选择器?
  • @Geeky 是点击但不是动画,请参阅我上面的编辑。
  • @teelou 我明白了。很难找到一种“防弹”的方式来做到这一点......
  • 这是一个荒谬的问题。这就像你在做elem = x; 然后询问如何获得elem 的先前值。你不能在 Javascript 中做到这一点。如果你用.bind() 覆盖this 的值,那么没有通用的方法可以恢复到没有.bind()this。如果您想访问this 中的某些值,那么这完全取决于具体情况。例如,点击处理程序可以访问event.target。没有通用的解决方案。

标签: javascript jquery ecmascript-6 this


【解决方案1】:

1. 最好的选择是将上下文存储在一个变量中,并且不要覆盖this

var context = this;
$('.element').on('click', function(event) {
  // context would be the this you need
  // this is the element you need
});

2. 如果您只针对单个元素,您可以从上面执行相反的操作,并将您要绑定处理程序的元素保存到一个变量中,然后在其中使用该变量处理程序:

var el = $('.element');
el.on('click', function(event) {
  // use el here
}.bind(this));

由于您使用 ES6 标记了问题,最好将上下文与 arrow function 绑定,因为使用 bind 更加冗长并且还创建了一个附加函数:

var el = $('.element');
el.on('click', (event) => {
  // this is the same as in the outer scope
  // use el here
});

3. 另一种选择是使用事件对象的target 属性,但这也可以是元素中的任何子元素(目标是调度事件的元素,而不是元素处理程序的边界),因此可能需要遍历 DOM 树才能找到所需的元素,这样效率较低。

var el = $('.element');
el.on('click', ({ target }) => {
  while (target.parentNode && !target.classList.contains('element')) {
    target = target.parentNode;
  }
  // here the target should be the element you need
});

【讨论】:

  • 感谢您的回答。 `target property` 在 animate 中不起作用。
  • 仅当 jQuery 对象是单例且仅包含一个 DOM 对象时,在事件处理程序之前保存元素才有效。如果它包含多个元素,那么您仍然不知道哪个元素触发了事件。
【解决方案2】:

如果您不使用.bind(),没有通用的方法可以访问this 的值。 Javascript 没有办法解除绑定并取回 this 本来的样子。相反,您必须查看每个单独的情况,看看是否有其他方法可以达到 this 本来的样子。

例如,正如我们中的一些人所说,在点击处理程序中,您可以访问event.target

jQuery animate 不会将任何参数传递给它的回调,因此如果您覆盖this,则没有通用方法可以返回触发元素。您必须再次返回选择器或将值保存在包含闭包中(人们通常为此使用名为 self 的变量)。

避免此问题的唯一通用方法是不使用.bind(),因此this 的值不会被替换。你可以这样做:

clickMe() {
    var self = this;
    $(".button-open").click(function(event) {
        // self is our ES6 object
        // this is the item that triggered the event
        console.log(this);
        self.openMe();
    });

【讨论】:

    【解决方案3】:

    如果你绑定了你的handler,那么你仍然可以在handler中通过event.target获取被点击的item。

    https://api.jquery.com/on/

    作为替代方案,您可以简单地做

    const self = this;
    

    const me = this;
    

    在您声明任何事件侦听器之前且不绑定任何函数。然后在处理程序中,您既可以使用this 来引用当前元素,也可以使用selfme 来引用父作用域。

    【讨论】:

    • animate 的情况如何?
    • 谢谢。我认为这是绑定后的唯一解决方案。谢谢!
    【解决方案4】:

    已经回答了,但这是我通常使用的模式:

    如果有单个'.element',下面的代码将起作用

    var el = $('.element');
    el.click(function(target, event){
        // target is the original this
        // this is the scope object
    }.bind(this, el[0]));
    

    但如果 '.element' 引用多个元素,那么下面的代码将处理它

    var clickHandler = function(target, event){
        // target is the original this
        // this is the scope object
    }.bind(this);
    
    $('.element').click(function(e) {
        return clickHandler(this, e);
    });
    

    【讨论】:

    • 顺便说一句,targetevent.target 不同——它们是两个不同的东西。
    • 是的,您在绑定中传递的是“el”(jquery 对象)
    • 那么目标不是原来的this。
    • 感谢您的更新。很好的解决方案,即使它有点难以理解/阅读。
    猜你喜欢
    • 2017-06-18
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多