ES6 中使用 jQuery $(this) 的问题

 

$('.js-bottom-btn').click((event) => {
    let flag = $(event.currentTarget).date('flag');
    ...
})

转1css

在老项目中开始改用 laravel-mix ES6 逐渐过渡。摸索中遇到在与 jQuery 一同使用时 箭头函数 中 $(this) 的含义发生了变化。node

 

遇到这个问题主要是没有搞清楚 箭头函数jquery

$('.js-bottom-btn').click(() => {
    let flag = $(this).date('flag');
    ...
});

转换为了:webpack

$('.js-bottom-btn').click(function() {
    let flag = $(_this).date('flag');
    ...
});

_this is undefinedlaravel

根据 jQuery click 文档 能够修改成:es6

$('.js-bottom-btn').click(event => {
    let flag = $(event.currentTarget).date('flag');
    ...
});

或者web

 

 

相似的问题:api

$('jquery-selector').each(() => {
    $(this).click();
})

须要改成:浏览器

$('jquery-selector').each((index, element) => {
    $(element).click();
})

Reference:dom

 

 

转2

前言

在es6里使用jquery时,习惯用es5中直接获取dom元素,如$('selector'),绑定clickhover等事件;若你也追求潮流,在选择器事件中使用箭头函数来定义,并用到$(this)的话, 那必定像我同样遇到了小小的困扰吧。

问题重现

$('[data-action="imgQRCodeCtrl"]')
        .hover(() => {
            !Base.browser.mobile && $(this).find('.qr-code').css({
                'height': ( $(this).find('.img').height() + 2 ) + 'px',
                'opacity': 1,
                'z-index': 1
            });
        }, () => {
            $(this).find('.qr-code').css({'opacity': 0, 'z-index': -1});
        })
        .click(() => {
            if(Base.browser.mobile){
                location.href = $(this).data('href');
            }
        });

乍一看,这段代码没什么问题,逻辑也很简单,就是在全部属性有data-action="imgQRCodeCtrl"的列表元素上绑定hoverclick事件,实现pc端hover时可以使内部的一个块显示或隐藏,移动端点击时获取当前属性上的href并进行跳转;

固然so easy,在过去的es5上按这种逻辑写彻底么有问题;but ES6里解析后,就有问题了;

以下是真实浏览器上加载的解析后的代码:

var $ = __webpack_require__("./node_modules/jquery/dist/jquery.js");
$(function () {
    var _this = this;
    //....
    $('[data-action="imgQRCodeCtrl"]').hover(function () {
        !_base2.default.browser.mobile && $(_this).find('.qr-code').css({
            'height': $(_this).find('.img').height() + 2 + 'px',
            'opacity': 1,
            'z-index': 1
        });
    }, function () {
        $(_this).find('.qr-code').css({ 'opacity': 0, 'z-index': -1 });
    }).click(function () {
        if(_base2.default.browser.mobile){
            location.href = $(_this).data('href');
        }
    });
});

this发生了什么!天哪,this被从新定义了!

即使没有真实运行这段代码,有点基础的,应该可以预见页面上发生了什么。。。

缘由分析

以下是Stack Overflow上大牛的解读:

This has nothing to do with Traceur and turning something off, this is simply how ES6 works. It's the specific functionality you're asking for by using => instead of function () { }.

If you want to write ES6, you need to write ES6 all the time, you can't switch in and out of it on certain lines of code, and you definitely cannot suppress or alter the way => works. Even if you could, you would just wind up with some bizarre version of JavaScript that only you understand and which would never work correctly outside of your customized Traceur, which definitely isn't the point of Traceur.

我理解的大意是说 “ES6的工做方式就是这样,跟编译无关,与写法有关;若想用ES6,最好全用ES6的写法,不能改变它本来的定义...”(英文很差,欢迎大神指正 >_< )

看到这儿,吓得我赶忙查了查文档。

原来箭头函数,不绑定本身的this,这一下就说通了;好好看看下面这句吧,不遇到问题时永远记忆模糊,哈哈。

箭头函数表达式的语法比函数表达式更短,而且不绑定本身的this,arguments,super或 new.target。这些函数表达式最适合用于非方法函数,而且它们不能用做构造函数。

问题解决

  • 方法一:弄清除原理后,就很简单了,绑定this的函数不使用箭头函数不就好了,以下试验果真ok:
$('[data-action="imgQRCodeCtrl"]')
        //...
        .click(function() {
            if (Base.browser.mobile) {
                location.href = $(this).data('href');
            }
        });
  • 方法二:不使用this, 使用event.currentTarget
$('[data-action="imgQRCodeCtrl"]')
        //...
        .click((event) => {
            if (Base.browser.mobile) {
                location.href = $(event.currentTarget).data('href');
            }
        });
  • 方法三:利用each函数循环绑定到每个小元素上,如此就不须要this
$('[data-action="imgQRCodeCtrl"]').each((index, element) => {
        let _this = element;
        $(_this).click(() => {
                if (Base.browser.mobile) {
                    location.href = $(_this).data('href');
                }
            });
    });

总结

以上的解决方法都能获得想要的效果,不过仍是提议使用 方法一 来解决,更简单直白,在维护和团队合做上会起很大做用,由于谁也不肯意读别人写的拐了十八个弯弯的代码吧。。。

这个问题挺小的,可能某些大牛看到后会鄙视我,不过喜欢这种遇到问题本身一步步解决并完美解释清楚的感受。

还在路上,有问题欢迎交流指正,之后还会多多以这种方式总结下。。。

参考连接
https://stackoverflow.com/questions/27670401/using-jquery-this-with-es6-arrow-functions-lexical-this-binding

原博客连接,欢迎来戳:
http://blog.oulafen.com/2017/11/22/es6-jq-this

相关文章
相关标签/搜索