君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

【OSSリーディング企画】BootstrapのJavaScriptを読み解く【その1】

f:id:karoten512:20180504205854p:plain

いきさつ

Bootstrap、すごい便利。

htmlタグさえドキュメントどおりにおけば*1

ルーセルは動くわモーダルは開くわアラートは出るわ、、、

f:id:karoten512:20180504211100j:plain

いつも本当にお世話になっております。

ただ、、、ただね、

なんで動くのか」について全然考えたことがなかったんですよ。

細かいところを調整しようと思った時に、

中がどうなっているのか分かっていないので、

手が完全に止まってしまう。。。

これじゃあ「ライブラリを使っている」のではなく、

「ライブラリに使われている」。そんな気がしてならない。。。

というわけで、OSSリーディングを始めました。

対象OSS

今回はBootstrapのモーダル周りについて読んでいきます。

読むファイルはこれ。

github.com

すでにビルドされている生のJavaScript

どうせならJavaScriptも軽く復習したい。

そういう思いもあります。

OSSを読むにあたって大切なこと

「全部は読まない。読みたいとこだけ」

なんだか懐かしい響きですね。

moto-neta.com

OSSを、はじめから全部読もうと思ってはいけません。

なんせOSS(今回はBootstrap)は、

「1000人以上の人が」

「何年もかけて」

開発をしているライブラリです。

はじめから全部読むのはツライツライ。

今回のゴール

何もしていないのに(JS書いていないのに)なんでボタンを押したらモーダルが開くのか

に絞って読んでいきます。

モーダルを開く処理までは読みません。

「ボタンを押したら」という部分に着目し、

ボタンに対してclickイベントを登録している部分を読み解きます。

また、その途中で即時関数が使われているので、即時関数についても簡単に触れます。

読んでいきます

Modalモジュールが宣言されている部分

/**
 * --------------------------------------------------------------------------
 * Bootstrap (v4.1.1): modal.js
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

var Modal = function ($$$1) {
   // いろいろな処理
}($);

だいたい1930行あたりにModalモジュール(モジュールという言い方が正しいのかどうかは微妙)が宣言されていますね。

Bootstrapでは様々な機能が使えますが、

これらはみなモジュールとして提供されています。

すごい乱暴に書くとこんな感じ。

var Modal = function ($$$1) {
   // いろいろな処理
}($);

var Carousel = function ($$$1) {
   // いろいろな処理
}($);

var Alert = function ($$$1) {
   // いろいろな処理
}($);

exports.Alert = Alert;
exports.Carousel = Carousel;
exports.Modal = Modal;
...

各モジュールで使われる変数は関数の中で定義され、カプセル化されています。

それにより、他のモジュールで使われている変数とぶつかったりすることはありません。

かしこい(小並感)。

exportsの意味について

そして、

exports.Alert = Alert;
exports.Carousel = Carousel;
exports.Modal = Modal;

exportsにはwindow.bootstrapオブジェクトが入っているよ。*2

つまり、もっと分かりやすく書くとこんな感じ。

window.bootstrap.Alert = Alert;
window.bootstrap.Carousel = Carousel;
window.bootstrap.Modal = Modal;

なので、コンソール上でwindow.bootstrapすると、

これらのモジュール(正確にはコンストラクタ)にアクセスすることができるよ。

f:id:karoten512:20180504213318p:plain

Modal用のボタンにクリックイベントをバインドしている部分

さて、Modalを開くためのボタンのhtmlを確認してみるよ。

<button type="button" data-toggle="modal" data-target="#exampleModal">
  Launch demo modal
</button>

これだけでいいらしいよ。ふざけてるね!

重要なのは、

data-toggle="modal"

という部分。

これを目印にして、

このdata属性を持っている要素にclickイベントをバインドしているよ。

こんな感じ!

// 2500行あたり
$$$1(document).on('click', '[data-toggle="modal"]', function (event) {
  // クリックした時に起こるイベント
}

え?

でもなんで勝手にclickイベントがバインドされるかって?

それは、この処理が即時関数の中で実行されているからだよ!

var Modal = function ($$$1) {
   // 即時関数の中
  $$$1(document).on('click', '[data-toggle="modal"]', function (event) {
    // クリックした時に起こるイベント
  }
}($);

一度JavaScriptが読み込まれると即時関数は勝手に実行されるので、

html上にdata-toggle="modal"さえ書いておけば、

勝手にclickイベントがバインドされるんだね!

即時関数の使い所

「一度しか実行されない処理」を即時関数で書くことが多いよ。

今回のように、

「特定の要素に対してイベントリスナを登録」

という処理は1度だけの実行でいいから、よく使われるよ。

即時関数のメリット

即時関数で処理を包むことにより、

変数のスコープが即時関数内に限定されるので、

グローバルスコープを汚さないよ!

巷のライブラリでも即時関数はよく見るよ。みてみてね!

まとめ

というわけで今回は、

モーダルを開くためのボタンに対してclickイベントが登録されている部分を確認してみました。

data-toggle='modal'さえ持っていればよいので、

ボタンだろうがlistだろうがdivだろうがなんでもモーダルが開けそうですね。

BootstrapのJavaScriptは、

定数がきちんと宣言されていたり、

jQueryからモーダルを操作できるようなAPIを提供していたり、

複数のモーダルを開くことができるような実装の仕方をしていたりと、

すごく勉強になる部分が多いので、ひきつづき読んできたいと思います。

*1:JavaScript書かなくてよいことも多い

*2:気になる人は1行目から読んでみよう。Boostrapがブラウザ上で実行される場合、exportsにはwindow.bootstrapオブジェクトが代入されているはずだ