jQueryとアロー関数の微妙な関係
昨日のJSLounge #0 jQueryだけで頑張らないWeb開発ハンズオンで@potato4dに教えてもらったアロー関数の話。
jQueryからvue.jsへ
ハンズオンのテーマは、jQueryを使って書かれたサイトをvue.jsに置き換えようというものでした。
$("button[type='submit']").html("<i class='glyphicon glyphicon-repeat'></i>");
$.ajax({
url: "https://example.com/events"
}).done(function(data){
$("button[type='submit']").html("送信する");
})
ボタンをローディング表示にしてAPIを呼び出し、終了後にボタンを元に戻す、というコードです。
ハンズオンでできる範囲ということで、API呼び出しそのものは$.ajaxのままでやってみましょう(つまり、ボタンの書換部分をvue.jsのv-ifで書くところをやってみよう)という感じでした。
<button v-if="!loading">送信する</button>
<button v-else><i class='glyphicon glyphicon-repeat'></i></button>
v-if='loading'
をつけたボタンと v-else
をつけたボタンを用意すると、JSコードでvue.loadingを変更するのに応じてボタンの表示が切り替わります。
this.loading = true;
$.ajax({
url: "https://example.com/events"
}).done(function(data){
this.loading = false;
})
このコードで実際動かしてみると、ボタンを押してローディングにはなるのですけど、その後ボタンがもとに戻らなくなってしまいました。
thisとアロー関数
}).done(function(data){
this.loading = false;
})
}).done(function(data){
this.loading = false;
})
問題はこの部分です。
jQuery単体でもたまに問題になるのですが、ajax関数のコールバック内のthisは、外部でのthisと異なるものを指します。$(this)
って書いたら動かなくなるアレです。
このため、this.loading
はvue.jsオブジェクトではない別のオブジェクトのloadingプロパティ(たぶん誰も参照していない)を書き換えるだけの空回り状態になってしまって、ボタンがもとに戻らなくなってしまっています。
@potato4dは「あとで説明するので、いったんこう書き換えてください」という豪快な説明で こう書き換えました。
}).done((data) => {
this.loading = false;
})
説明してもらうのを待てずにググったところによると、JavaScript ES2015で導入されたアロー関数というものです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions
従来のfunction(data){
で書くと、その中のthisは文脈によって変化します。
一方アロー関数を使った場合、関数の中であっても、thisは関数の外と同じものを指します。つまりこの場合だと引き続きvue.jsオブジェクトにアクセスすることができるので、this.loading = false;
はvue.jsのコードとして動作します。
アロー関数とIEの微妙な関係
アロー関数は新しいJavaScriptの書き方なので、環境によって動かないことがあります。具体的には、IE11、iOS9、Android4あたりでは動きません。
http://caniuse.com/#feat=arrow-functions
vue.jsを勉強しに来た参加者がIE11なんて使わないことを見越してアロー関数書いた @potato4d はハンズオン上手だと思うのですけど、実際運用する上でAndroid4をバッサリ切るのは無理なので、その辺のところを質疑応答のときに聞いてみました。
まず、IE11を含む古いブラウザでも動かす方法として、Babelをつかって新しい書き方を古いOSでも動くコードにコンパイルしてしまう方法があります。ある程度の規模になるとこのやり方が必須だし、個人的にはこっちを使いたいのですが、「npm
を入れてwebpack
からgulp
をつかってBabel
を呼び出してね」というと、環境設定だけでハンズオンが終わってしまうし、jQueryから乗り換えようという人には厳しい予感がします。
で、お手軽な解決法としては、従来のjQueryでも使われていたselfを使うテクニックが使えます。
var self = this;
self.loading = true;
$.ajax({
url: "https://example.com/events"
}).done(function(data){
self.loading = false;
})
selfにthisを退避した上で使うことで、doneの中でも外と同じオブジェクトにアクセスすることができます。
vue.jsを使うに当たってはwebpackを始めとした近代JavaScript環境の勉強が必須だと思っていたのですけど、なるほどコンパクトにまとめる方法もあるものだなあと思いました。
Author And Source
この問題について(jQueryとアロー関数の微妙な関係), 我々は、より多くの情報をここで見つけました https://qiita.com/mogya/items/1d6a0eadc7e0f9d2982b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .