【OSSリーディング企画】BootstrapのJavaScriptを読み解く【その1】
いきさつ
Bootstrap、すごい便利。
htmlタグさえドキュメントどおりにおけば*1、
カルーセルは動くわモーダルは開くわアラートは出るわ、、、
いつも本当にお世話になっております。
ただ、、、ただね、
「なんで動くのか」について全然考えたことがなかったんですよ。
細かいところを調整しようと思った時に、
中がどうなっているのか分かっていないので、
手が完全に止まってしまう。。。
これじゃあ「ライブラリを使っている」のではなく、
「ライブラリに使われている」。そんな気がしてならない。。。
というわけで、OSSリーディングを始めました。
対象OSS
今回はBootstrapのモーダル周りについて読んでいきます。
読むファイルはこれ。
すでにビルドされている生のJavaScript。
どうせならJavaScriptも軽く復習したい。
そういう思いもあります。
OSSを読むにあたって大切なこと
「全部は読まない。読みたいとこだけ」
なんだか懐かしい響きですね。
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すると、
これらのモジュール(正確にはコンストラクタ)にアクセスすることができるよ。
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オブジェクトが代入されているはずだ