前回の記事の続き。
dojoでカスタムウィジェットを作成するチュートリアルを読んでいたけど
マウスオーバー時のアクションの部分でundefinedエラーが発生していた。
該当のコードはこんな感じ。
// colors for our background animation baseBackgroundColor: '#fff', mouseBackgroundColor: '#def', postCreate: function(){ // Get a DOM node reference for the root of our widget var domNode = this.domNode; // Run any parent postCreate processes - can be done at any point this.inherited(arguments); // Set our DOM node's background color to white - // smoothes out the mouseenter/leave event animations domStyle.set(domNode, "backgroundColor", this.baseBackgroundColor); // Set up our mouseenter/leave events - using dojo/on // means that our callback will execute with `this` set to our widget on(domNode, 'mouseenter', function (e) { this._changeBackground(this.mouseBackgroundColor); }); on(domNode, 'mouseleave', function (e) { this._changeBackground(this.baseBackgroundColor); }); }, _changeBackground(toCol) { ...
チュートリアル通りに実装したのですが、
this._changeBackground
やthis.mouseBackgroundColor
がundefined
だと怒られる...
で、調べてわかったことですが
これチュートリアルの記述が間違ってますね。
正しくはこうです。
(onメソッド内部のみ)
on(domNode, 'mouseenter', lang.hitch(this, '_changeBackground', this.mouseBackgroundColor));
つまり、lang.hitch
を使う必要があります。
なんで?という部分については
lang.hitch()
のリファレンスにサンプルコード含めてわかりやすく書いてた。
dojo/_base/lang — The Dojo Toolkit - Reference Guide
require(["dojo/on"], function(on){ var processEvent = function(e){ this.something = "else"; }; on(something, "click", processEvent); });
こういう書き方をしてもうまくいかないのは
非同期のコールバック関数(on
で呼び出してる関数)のcontext
が変わっているからなんだと。
context
という単語にしっくりくる日本語訳はわからんが
「this
が示すもの」が変わっている、と考えるとよさそう。
つまり、関数を定義している時のthis
と、実際に非同期でコールバックが呼ばれている時のthis
は別物ってことですね。
それを回避するために、lang.hitch
を使います。
上の例だと次のように書けばよい。
require(["dojo/on", "dojo/_base/lang"], function(on, lang){ var processEvent = function(e){ this.something = "else"; }; on(something, "click", lang.hitch(this, processEvent)); });