1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vue.jsを使ってドロワーメニューを作ってみた

Posted at

こんにちは。

Vue.jsやReactが流行っていることもあり、つい最近Vue.jsについて学び始めました。(まだ触れてみたくらい?)

Vue.jsに触れてみて何かに活用してみたいなと思ったので、ドロワーメニューに活用したものを学習ログとしてここに残そうと思います。

ドロワーメニューの完成版

簡易ではありますが、Vue.jsを使って下記gifのようなドロワーメニューを作ってみました。

ドロワーメニュー.gif

Vue.jsを使って書いた完成版のコードは下記になります。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ドロワーメニュー</title>
  <link rel="stylesheet" href="style.css">
  <script src="https://unpkg.com/vue@next"></script>
  <script src="app.js" defer></script>
  <script src="script.js" defer></script>
</head>
<body>
  <div id="app">
    <nav class="header__nav" :class="{'is-drawerActive' : isActive}">
      <h2 class="visuallyHidden">サイト内メニュー</h2>
      <button type="button" class="hamburger" aria-controls="globalNav" :aria-expanded="isActive" @click="drawer">Menu</button>
      <ul id="globalNav" class="globalNav">
        <li v-for="i in 5">メニュー{{ i }}</li>
      </ul>
    </nav>
  </div>
</body>
</html>
style.css
* {
  margin: 0;
  padding: 0;
}

body {
  padding: 5rem;
  background-color: #fff;
}

.visuallyHidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  border: 0;
  white-space: nowrap;
  clip-path: inset(50%);
}

.globalNav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: 5rem;
  background-color: #212121;
  color: #fff;
  transition: transform .3s ease-in-out;
  transform: translate3d(100%, 0 , 0);
}

.is-drawerActive .globalNav {
  transform: translate3d(0, 0 , 0);
}

.hamburger {
  position: fixed;
  top: 3rem;
  right: 3rem;
  z-index: 2;
  width: 5rem;
  height: 5rem;
  border-radius: 50%;
  background-color: transparent;
  border: 1px solid currentColor;
  mix-blend-mode: exclusion;
  color: #fff;
  cursor: pointer;
  appearance: none;
}

app.js
Vue.createApp({
  data() {
    return {
      isActive: false,
    };
  },
  methods: {
    drawer() {
      this.isActive = !this.isActive;
    }
  }
}).mount("#app");

Vue.jsを使ったドロワーメニューの作り方

Vue.jsを使ったドロワーメニューの作り方について下記に記載していきます。

基本的なHTML

Vueを使用するためにはインストールをする必要がありますが、今回はCDNを利用しているため、headタグ内に下記コードを記載します。

index.html
<head>
  <script src="https://unpkg.com/vue@next"></script>
</head>

CDNを読み込んだ後は、基本的なHTMLとJSファイル内にVueのインスタンスを作成していきます。
今回はVueで操作していきたい要素に「app」というid名に付けています。

index.html
<body>
    <div id="app">
      <nav class="header__nav">
        <h2 class="visuallyHidden">サイト内メニュー</h2>
        <button type="button" class="hamburger" aria-controls="globalNav" aria-expanded="false">Menu</button>
        <ul id="globalNav" class="globalNav">
          <li>メニュー1</li>
          <li>メニュー2</li>
          <li>メニュー3</li>
          <li>メニュー4</li>
          <li>メニュー5</li>
        </ul>
      </nav>
    </div>
</body>
app.js
Vue.createApp({
  data() {
    return {
        
    };
  },
}).mount("#app");

Vueのディレクティブを使ってメニューを書き換える

基本的なHTMLを書いた後は、Vueの「v-for」ディレクティブを使って繰り返し処理をしていきます。
下記の書き方をすることによって、メニュー1〜メニュー5までを画面上に映し出すことができます。

index.html
 <li v-for="i in 5">メニュー{{ i }}</li>

「v-for」を用いてメニューを書き換えたHTMLが下記になります。

index.html
<body>
    <div id="app">
      <nav class="header__nav">
        <h2 class="visuallyHidden">サイト内メニュー</h2>
        <button type="button" class="hamburger" aria-controls="globalNav" aria-expanded="false">Menu</button>
        <ul id="globalNav" class="globalNav">
          <li v-for="i in 5">メニュー{{ i }}</li>
        </ul>
      </nav>
    </div>
</body>

メソッドを使ってドロワーメニュを表示/非表示にする

「is-drawerActive」クラスが付与されるとメニューが出てくる仕様なため、「v-on」と「v-bind」ディレクティブ、さらにメソッドを使ってclassの付け外しが出来るようにしていきます。

buttonタグをクリックしたときに「is-drawerActive」クラスの付け外しが出来るようにしたいため、buttonタグに「v-on」ディレクティブを、navタグに「v-bind」ディレクティブを付け加えます。

index.html
    <div id="app">
      <nav class="header__nav" :class="{'is-drawerActive' : isActive}">
        <h2 class="visuallyHidden">サイト内メニュー</h2>
        <button type="button" class="hamburger" aria-controls="globalNav" :aria-expanded="isActive" @click="drawer">
          Menu
        </button>
        <ul id="globalNav" class="globalNav">
          <li v-for="i in 5">メニュー{{ i }}</li>
        </ul>
      </nav>
    </div>

また、JSファイルにメソッドを定義していきます。

app.js
Vue.createApp({
  data() {
    return {
      isActive: false,
    };
  },
  methods: {
    drawer() {
      this.isActive = !this.isActive;
    }
  }
}).mount("#app");

dataプロパティ内にてisActiveの値をfalseに定義しておき、drawerメソッドでfalseとtrueが切り替わるようにしています。

そのため、属性を操る「v-bind」を用いることで、「isActive」がtrueの時に「is-drawerActive」クラスが付与され、falseの時には「is-drawerActive」クラスが外されます。

ちなみにですが、「v-on」と「v-bind」は省略記法を用いています。

HTML
「v-on」:イベントを指定する
<button v-on:click="drawer">Menu</button>
<!-- 省略記法 -->
<button @click="drawer">Menu</button>


「v-bind」:属性を操作する
<nav class="header__nav" v-bind:class="{'is-drawerActive' : isActive}">
<!-- 省略記法 -->
<nav class="header__nav" :class="{'is-drawerActive' : isActive}">

終わりに

Vue.jsを使えば、JavaScriptよりも少ない記述量でドロワーメニューを動かせることがわかりました。
もっと応用できるようにVue.jsを学びたいと思うと同時に、JavaScriptの理解も深めていきたいと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?