$('.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
在es6裏使用jquery時,習慣用es5中直接獲取dom元素,如$('selector')
,綁定click
或hover
等事件;若你也追求潮流,在選擇器事件中使用箭頭函數來定義,並用到$(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"
的列表元素上綁定hover
及click
事件,實現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'); } });
this
了$('[data-action="imgQRCodeCtrl"]').each((index, element) => { let _this = element; $(_this).click(() => { if (Base.browser.mobile) { location.href = $(_this).data('href'); } }); });
以上的解決方法都能獲得想要的效果,不過仍是提議使用 方法一 來解決,更簡單直白,在維護和團隊合做上會起很大做用,由於誰也不肯意讀別人寫的拐了十八個彎彎的代碼吧。。。
這個問題挺小的,可能某些大牛看到後會鄙視我,不過喜歡這種遇到問題本身一步步解決並完美解釋清楚的感受。
還在路上,有問題歡迎交流指正,之後還會多多以這種方式總結下。。。
原博客連接,歡迎來戳:
http://blog.oulafen.com/2017/11/22/es6-jq-this