VanillaJavaScriptで最初からタブコンポーネントを実装する
バニラJavaScriptと羽ばたき不可能なウィットだけを使用して、よく知られているタブコンポーネントを再作成することで、開発スキルを磨きましょう。
表面的には、タブはかなり退屈に見えるかもしれません。 私たちは皆、彼らが何をしているのかを知っており、あまり考えずにWebブラウザーで日常的に使用していますが、ネイティブブラウザーテクノロジーのみを使用してモバイルデバイスで適切に機能する最新の再利用可能なタブコンポーネントを設計することは、実際には非常に困難であり、 「現実世界」のコードを作成する絶好の機会です。
基本要件
タブコンポーネントは次のようにする必要があります。
- レスポンシブ
- 再利用可能
- ネスタブル
- デフォルトのタブを設定できます
それを手に入れよう! 最初にコードから始め、次に何が起こっているのかを分析します。
マークアップ
タブコンポーネントの基本的なHTMLマークアップは次のとおりです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Gator tabs</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="gator-tabs-container">
<ul class="gator-tabs-header">
<li>The nest</li>
<li class="default-gator-tab">Hello world!</li>
<li>Rise of the gator</li>
</ul>
<ul class="gator-tabs">
<li class="gator-tabs-container">
<ul class="gator-tabs-header">
<li>Nested 1</li>
<li class="default-gator-tab">Nested 2</li>
</ul>
<ul class="gator-tabs">
<li class="gator-tab">Some eggs in nest one</li>
<li class="gator-tab">Some eggs in nest two</li>
</ul>
</li>
<li class="gator-tab">Hello world from tab one!</li>
<li class="gator-tab">Believe me I know tabs, I have the best tabs. Nobody does tabs like I do.</li>
<li class="gator-tab">For now the eggs lay dormant but soon the gators will rise from the swamps.</li>
</ul>
</div>
<script src="main.js"></script>
</body>
</html>
スタイリング
そして、すべてを美しく見せるためのいくつかのCSSスタイル:
/* minimal reset */
* {
margin:0;
border:0;
padding:0;
box-sizing:border-box;
list-style:none;
}
body{
background-color: #333;
/* because serifs are gross (IMO) */
font-family: sans-serif;
}
.gator-tabs-container{
display:flex;
flex-direction:column;
width:100%;
}
.gator-tabs-header {
background-color:#DFA612;
display:flex;
flex-wrap:wrap;
padding:.375rem;
}
.gator-tabs-header > li {
color:#fff;
cursor:pointer;
flex-grow:1;
padding:.375rem;
font-size:1.125rem;
}
.gator-tabs {
display:flex;
}
.gator-tab {
padding:1rem;
color:#fff;
}
JavaScriptコード
それでは、簡単なJavaScriptで魔法を起こしてみましょう。
function tabify( element ){
const header = element.querySelector('.gator-tabs-header');
const content = element.querySelector('.gator-tabs');
const tab_headers = [...header.children];
const tab_contents = [...content.children];
tab_contents.forEach( x => x.style.display = 'none');
let current_tab_index = -1;
function setTab( index ){
if( current_tab_index > -1 ){
tab_headers[ current_tab_index ].style.fontWeight = 400;
tab_contents[ current_tab_index ].style.display = 'none';
}
tab_headers[ index ].style.fontWeight = 800;
tab_contents[ index ].style.display = 'flex';
current_tab_index = index;
}
default_tab_index = tab_headers.findIndex( x => {
return [...x.classList].indexOf('default-gator-tab') > -1;
});
default_tab_index = default_tab_index === -1 ? 0 : default_tab_index;
setTab( default_tab_index );
tab_headers.forEach((x,i) => x.onclick = event => setTab(i));
}
// this is where the magic happens!
[...document.querySelectorAll('.gator-tabs-container')]
.forEach(x => tabify(x));
モバイルでのアプリのスクリーンショットは次のとおりです。
要約/内訳
最初の要件はレスポンシブなものを作成することでした。これは、 Flexboxとflex-wrap
プロパティを使用して簡単に解決できるため、モバイルでタブヘッダーが互いに重なり合うようになります。
コードを再利用可能にするのは最初は難しいように思われるかもしれませんが、コードをtabify
という関数にラップすることで、必要なクラス/タグ構造を満たすタブに何でも作成できます。 これにより、次の要件であるネスト可能が自動的に設定されます。
最後の要件は、ページが開いたときに選択されるデフォルトとしてタブを設定する機能です。 これは、default-gator-tab
クラスを目的のタブヘッダーに追加することで実現されました。スクリプトは、このクラスの最初のタブヘッダーのインデックスを見つけ、それを使用して最初のタブを設定します。
前回の記事では、React を使用したタブの作成について説明しましたが、正直なところ、この場合、Reactがプレーンな古いJavascriptよりも優れている点を見つけるのは難しいです。 (propsの代わりに)クラス名を使用してデフォルトタブなどの構成をスクリプトに渡すことができ、フレームワークのオーバーヘッドなしでReactバージョンとほぼ同じ量のコードを使用しています!
必要に応じて、アニメーションやより複雑な機能を含める必要があるものを簡単に拡張できますが、それはあなたに任せます。