Edited at

BulmaのハンバーガーメニューをVue.jsで実装する


はじめに

こんにちは、普段はサーバーサイドを担当しているsekiと申します。

今、個人開発で掲示板を作っており、UIフレームワークにBulmaを採用しました。が

初っ端、公式リファレンスからコピペしたヘッダーのハンバーガーメニューが動きませんでした。:tired_face:

調べても日本語の記事で解決方法が出てこなかったので、解決方法を簡単にまとめたいと思います。 すでに似た記事がqiitaに投稿されていました:bow:

どうやらJavaScriptを導入しないと動かないみたいです。

今回はVue.jsを使って動かしてみたいと思います:wink:


1.Starter templateにナビゲーションバーを表示させてみる

公式リファレンスのクイックスタート用のテンプレートナビゲーションバーを表示させてみたいと思います。


index.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello Bulma!</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<body>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="https://bulma.io">
<img src="https://bulma.io/images/bulma-logo.png" width="112" height="28">
</a>

<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>

<div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item">
Home
</a>

<a class="navbar-item">
Documentation
</a>

<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
More
</a>

<div class="navbar-dropdown">
<a class="navbar-item">
About
</a>
<a class="navbar-item">
Jobs
</a>
<a class="navbar-item">
Contact
</a>
<hr class="navbar-divider">
<a class="navbar-item">
Report an issue
</a>
</div>
</div>
</div>

<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<a class="button is-primary">
<strong>Sign up</strong>
</a>
<a class="button is-light">
Log in
</a>
</div>
</div>
</div>
</div>
</nav>
</body>
</html>


ブラウザで確認するとしっかりヘッダーが表示されています!!

スクリーンショット 2019-02-12 21.10.01.png

しかし、レスポンシブ時のハンバーガーメニューをクリックしてもうんともすんとも言いません・・・・困りました。

それでは早速Vue.jsを使用してハンバーガーメニューを動かしてみましょう!


Vue.jsでハンバーガーメニューを動かす

まずはCDNでVue.jsを読み込みます。


index.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello Bulma!</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <!-- 追加する行 -->
</head>
<body>
~省略~

これでVueを使えるようになりました。

続いて、nav要素をdivで囲みます。


index.html

<body>

<div id="app">    <!-- 追加する行 -->
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="https://bulma.io">
<img src="https://bulma.io/images/bulma-logo.png" width="112" height="28">
</a>

~省略~
</nav>
</div> <!-- 追加する行 -->


次にVueインスタンスを作成します。


index.html

<script>

var app = new Vue({
el: '#app',
data: {
isOpen: false
}
})
</script>

ここで定義したisOpenはハンバーガーメニューを表示するために使用します。

次はクリックイベントを設定して実際にハンバーガーメニューを開いてみましょう。


index.html

<nav class="navbar" role="navigation" aria-label="main navigation">

<div class="navbar-brand">
<a class="navbar-item" href="https://bulma.io">
<img src="https://bulma.io/images/bulma-logo.png" width="112" height="28">
</a>

<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" @click="isOpen = !isOpen" v-bind:class="{'is-active': isOpen}"> <!-- 変更する行 -->
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>

<div id="navbarBasicExample" class="navbar-menu" v-bind:class="{'is-active': isOpen}">     <!-- 変更する行 -->
<div class="navbar-start">

~省略~


これでハンバーガーメニューが動くようになりました!

スクリーンショット 2019-02-13 21.54.12.png

最後に変更した二箇所の解説をさせていただきます。


変更箇所の一行目

<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" @click="isOpen = !isOpen" v-bind:class="{'is-active': isOpen}">

この行には@click="isOpen = !isOpen"v-bind:class="{'is-active': isOpen}">が追加されています。

@click="isOpen = !isOpen"でなにが起きてるか解説します。

@clickはクリックを検知してisOpen = !isOpenを実行します。

つまり、ハンバーガーメニューをクリックした時(@click)にisOpenに格納されている真理値が反転する処理(isOpen = !isOpen)が行われます。

v-bind:class="{'is-active': isOpen}">ではisOpenがtrueの時にclassにis-activeが追加される処理が行われています。


変更箇所の二行目

<div id="navbarBasicExample" class="navbar-menu" v-bind:class="{'is-active': isOpen}">

ここでは先ほどと同じようにv-bind:class="{'is-active': isOpen}"が追加されています。

ハンバーガーメニューがクリックされた時にこの要素のclassにis-activeが追加されます。


まとめ

色々と書きましたが、やっていることはただ要素のclassにis-activeを追加したり消したりしているだけです。

BulmaはどのJavaScriptの環境にも適応できるので、柔軟性があってとても便利ですね:v: