event.currentTargetとevent.targetの違い

See the Pen used target by nakanishi (@nakanishi) on CodePen.

event.target と event.currentTargetは違う

イベントが発生した時に、イベントリスナーでイベントオブジェクトを取得することができるが、このイベントリスナーの event.target と event.currentTarget は「異なる性質」を持つので注意したい。

確認:イベントリスナーとは

イベントリスナーとは、イベントターゲット(HTMLの各種要素=ノード等)に対して、イベント(clickやhover)が発生した際に実行する「関数、もしくはオブジェクト」を関連付ける仕組みのこと。具体的には、あるdivがマウスオーバーされた時に特定の関数を実行する、といった機能を実装する際に使われる。

//ES6です
'use strict';

class AddHover {
  constructor(target) {
    this.target = target;
    this.hover(this.target);
    console.log("new"+this.target);
  }
  
  hover(target) {
    let $hoverTarget = $(target);
    let rolloverClass = 'hover';
    $hoverTarget.hover(
    //ここがイベントリスナー
      (event) => {
        $(event.currentTarget).addClass(rolloverClass);    
      },
      (event) => {
        $(event.currentTarget).removeClass(rolloverClass); 
      }
    )
  }
}

イベントオブジェクトとは

イベントリスナーで指定する関数の第一引数に、イベント・オブジェクトが入る。(event) => {} はfunction(event){}と同じ意味。

//ES6です
$hoverTarget.hover(
 (event) => {
    $(event.currentTarget).addClass(rolloverClass);    
    },
  (event) => {
    $(event.currentTarget).removeClass(rolloverClass); 
  }
)

event.currentTargetとevent.targetの違い

See the Pen used target by nakanishi (@nakanishi) on CodePen.

やっと本題だが、event.currentTargetは、イベントが付けられたノードを返し、event.targetは実際にイベントが発生したノードを返す。

上記のコードデモでは、nakaと書かれたdivはcurrentTargetを指定しているため、正常に動くが、その下のdivではラテン語のダミーテキストにマウスオーバーをするとテキスト部分だけに色が付いてしまい意図した挙動とならない。こちらはtargetを指定しているためだ。

targetはイベントリスナーを付けたノードではなく、マウスオーバー「イベントが発生したノードそのもの」を返すために、今回の例ではダミーテキストが入った<p>ノードを返す。結果としてバックグラウンドカラーが、pの部分だけに指定されてしまう。

実装時には、HTMLの構造、及びクラス付に注意しながらtargetとcurrentTargetを使い分ける必要がある。

ES6 + jQuery でマウスホバーを実装する

See the Pen used es6 hover class new by nakanishi (@nakanishi) on CodePen.

AddHoverクラスの中に機能を実装し、ページ読み込み時にAddHoverクラスをnewでたたく。

注意:event.targetとevent.currentTargetの違いについて

次の記事を参照

 

ES6のクラス構文

See the Pen mOPoaG by nakanishi (@nakanishi) on CodePen.

class クラス名/冒頭は大文字  { 内容 }

内容にはコンストラクタとメンバ変数とメソッドを書く。

  • constructor(引数1,引数2) { this.引数1; this.引数2; this.call();等々}
  • メソッドはclassの中、constructorの外に書く call(){}

クラスを使うときはnew クラス名()、もしくはvar 変数名 = new クラス名()

new クラス名()をすると、コンストラクタに書かれた内容が実行される。変数名に代入すると、オブジェクトが変数に入る。

機能単位でクラスを作って、newをして実行するのが良い

最終的には機能毎にファイルを分けて、クラスを作成し、export/importをして、必要な時にnewで呼び出すのがよい。

CodePenでEmmetを使う

http://docs.emmet.io/cheat-sheet/

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-14-5-53-44

Emmetとは

Emmet は元々 Zen-coding という名前で開発されていた HTML と CSS のショートカットのようなもので、tag名や()を全て入力しなくても、簡略化した記法の最後に tab を押すことで、HTML や CSS へ展開できるコーディングのためのシステムです。

Emmetを各種エディター、CodePenで使うには

Emmet は Sublime Text や Atom 等、ほとんどのエディターのためにプラグインが用意されており、使用することができます。

CodePenでは最初からEmmetを使うことができます。

Emmetの例

Emmetの一例を以下に記します。全てのEmmetについては本家サイトのショートカット集から確認できます。http://docs.emmet.io/cheat-sheet/

See the Pen used emmet by nakanishi (@nakanishi) on CodePen.

CodePenでES6以上をBabelでコンパイルして使う

ES6とBabel

ES6ではclass構文が使えるようになり、素直なオブジェクト指向プログラミングが可能になったが、ES6は現状サポートしていないブラウザもある。そのためES6で書いたスクリプトはBabelを使ってES5にトランスコンパイルして使用する。

CodePenとBabel

CodePenではBabelをプリプロセッサーとして用いることができ、これによってES6記法のJSをES5記法に変換することができる。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-13-14-31-37

ES6のfunction記法抜粋

ES6はarrow functionが使える。これとjQueryを組み合わせた記法を以下に示す。

特に、arrow functionとjQueryのhoverメソッドを用いる場合にthisの扱いに注意することがポイントである。

See the Pen NbNaXY by nakanishi (@nakanishi) on CodePen.

CoffeeScriptとの違い

CofeeScriptの開発はほぼ停止しているらしく、かつ一番必要とされていたクラス構文がES6で実装されたことから、基本的にはES6を中心に書いていけばよいものと思われる。

  • {}も()も;も基本的に必要で、通常のJSと同じ。
  • インデントは内容には関係しない (CoffeeScriptはインデントによって内容が変わる)
  • import,export,require関係は微妙に異なるようなので注意
  • クラス構文が使えるのはどちらも共通しているが、書き方が少し異なるようだ

よくあるヘッダーのナビを作る

See the Pen used nav by nakanishi (@nakanishi) on CodePen.

HTMLの構造

navを用いて、その中にul要素を配置する。

li要素の点と余計な空白を消す

li {
 list-style: none;
 padding: 0;
 margin: 0;
}

liを左に寄せて、隙間を調整する

li {
 text-align: center;
 float: left;
 border: solid 1px;
 padding: 0px 10px;
 margin-left: -1px;
}
list:first-child {
 margin-left: 0;
}

aリンクを修正

a {
 text-decoration: none;
 color: black;
}

補足

ボーダー1pxを追加すると、線が2本重なって2pxの線になってしまう。この場合は、全体をmargin: -1pxし、さらにfirst-childだけmargin: 0にすればよい。

各アイテム間の隙間はmarginではなくpaddingを使用する。