はじめに
近年、素のJavaScript(Vanilla JS)の進化は著しく、数々の便利な機能がリリースされています。しかしながら、ネット上の活用事例が未だ充実しておらず大体の人は諦めてフレームワーク(Vue,Angular,React等)を利用してロックインされているのが現状です。
そこで本記事では、実際にWebComponentsを利用して作成をした、Excelライクな表作成ライブラリを用いてWebComponentsの機能を紹介します。(実際に作成したライブラリはGITに公開しています)
WebComponentsのメリットは一言でいうとカプセル化です。WebComponentsの主な機能は以下の通り3つあり(本当は4つですが4つ目は推奨されていないので省略)、WebComponentsの価値はそれらの機能を全て特定のフレームワークに依存せず実現できることにあります。
- WebComponentsの3機能
- CustomElements:タグに紐づいた、そのタグの振る舞いのカプセル化
- ShadowDOM : DOMの隠蔽化やCSSの分離といったカプセル化
- ESModules : js Objectのカプセル化
実際のソースコードと対応させて見てみよう!
まずは完成した画面です。Excelっぽく複数選択やソート、行追加/削除も可能。
それでは、HTMLから見ていきます。非常にシンプルだと感じるはず。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="./images/favicon.ico" type="image/vnd.microsoft.icon">
<link rel="icon" href="./images/favicon.ico" type="image/vnd.microsoft.icon">
<title>excelライクなテーブル</title>
</head>
<body>
<h3>右クリックで行追加/削除できます</h3>
<local-sheet></local-sheet>
<script type="module" src="./js/local-sheet.js"></script>
</body>
</html>
-
<local-sheet></local-sheet>
がCustom Elementsと呼ばれている部分です。今まではひたすらdivを使っていましたが、独自のタグ名だけで使いまわせるパーツを作れます。 - 上記の中身(中身はlocal-sheet.jsに記述)が後述しますがShadowDOMというものになっており、通常のDOMツリーの要素の下に隠れたDOMツリーを取り付けています。ShadowDOMを使用するメリットは、何といっても独立したDOMとして扱えるためcssを該当のツリーにのみ適応する等、他のDOMから影響を受けない独立したツリーとして扱える点です。
-
<script type="module" src="./js/local-sheet.js"></script>
の部分がESModulesの部分で、local-sheet.jsをモジュールとして呼び出しています。モジュール化のメリットとしてはモジュール化したjsから別のjsを呼び出せるようになる点がありますが、1点注意事項としてローカルではCORS policyに引っかかるようになるため動かなくなります。ブラウザのセキュリティを下げるか、おとなしくサーバ上で動作させてください。
次にHTMLでモジュールとして呼び出したlocal-sheet.jsの中身を見てみます。
//===============================================================
// 画面表示部分のJS
//===============================================================
//===============================================================
// ShadowDOM生成
//===============================================================
class LocalSheet extends HTMLElement {
constructor() {
super();
//HTMLから分離されたノード(ShadowDOM)を作成(親のドキュメントのCSSなどに影響されない)
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<!-- ShadowDOM用css読み込み -->
<link rel="stylesheet" href="./css/local-sheet.css">
<link rel="stylesheet" href="./css/filter.css">
<!-- table構造 -->
<table id="localSheet" style="table-layout:fixed;"">
<thead id="localSheetThead">
</thead>
<tbody id="localSheetTbody">
</tbody>
</table>
~~~ 中略 ~~~
<div id="tableFilter"></div>
`;
}
}
//===============================================================
// タグで呼び出せるように設定 + 基幹関数実行
//===============================================================
(function main() {
// local-sheetという名前でLocalSheetクラスを登録する
customElements.define("local-sheet", LocalSheet);
import ("./local-sheet-function.js")
.then((obj) => {
// 各モジュールには、引数objのプロパティからアクセスできる。
obj.localSheetFunction();
});
})();
-
customElements.define("local-sheet", LocalSheet);
がCustom Elementsの部分。HTMLで<local-sheet></local-sheet>
と記載すれば呼び出せるようにしています。 -
class LocalSheet extends HTMLElement {
がShadowDOMの部分。 -
import ("./local-sheet-function.js")
がESModulesの部分。jsから別のjsをインポートしています。
最後に、local-sheet.jsからインポートされているlocal-sheet-function.jsの中身です。
//===============================================================
// テーブル構築をする基幹となる関数
//===============================================================
export function localSheetFunction() {
if (dbUseFlg == 1){
let uri = getUri();
const encodeUri = encodeURI(uri);
fetch(encodeUri)
//KAGRA API実行
.then(function(res){
return(res.json());
})
.then(function(json){
let arrayData = JSON.stringify(json["return"]);
arrayData = JSON.parse(arrayData);
//th入力
arrayThData = arrayData[0];
//thを削除
let exe = [0];
for(let i=0; i<exe.length; i++){
arrayData.splice(exe[i]-i, 1);
}
//tdを入力
arrayTdData = arrayData;
setTableInfo();
return(json.setDisable);
})
.catch(function(err){
console.log(err);
});
} else{
setTableInfo();
}
}
- 見るべき点は
function
先頭についているexport
です。別のjsから呼び出されるためには、export
の記載が必要です。
さいごに
いかがだったでしょうか。使い慣れてくると非常に便利で、Vanilla JSのため陳腐化することの無い普遍的な技術なのでWebComponentsの使い手が増えることを祈っています。
また、本記事の説明で使用したソースはGIT上に公開していますので、ご興味があれば以下参照リンクからアクセスしてください。
本記事で使用したコード(GitHub)