Aug 15, 2020

「Nuxtでプログを構築しよう!!」の9回目。ヘッダーメニューを作ってみよう。

「Nuxt でプログを構築しよう!!」の 9 回目です。画面も整ってきましので、今回はヘッダーメニューを作ってみたいと思います。ヘッダーにはブログ説明のリンク、メニュー、言語切替ボタンを配置しようと思います。メニューにはマテリアルアンコンも入れたいと思います。

Header コンポーネントの作成

Header コンポーネントは Logo コンポーネント、Menu コンポーネント、Lang コンボーネントの構成にします。

/components/Header.vue before
<template>
  <div>Header</div>
</template>
<template>
  <header>
    <div class="logo">
      <Logo />
    </div>
    <div class="menu">
      <Menu />
    </div>
    <div class="lang">
      <Lang />
    </div>
  </header>
</template>
<style>
header {
  display: flex;
  justify-content: space-between;
}
</style>

スタイルシートに、display:flex、justify-content: space-betweenと記載しているのは横並びで中央左右にコンポーネントを配置するためです。

Tip flexbox を使うと簡単に子要素の並びを制御することができます。子要素を横ならびに並べたい時は、親要素に display:flex;と記載します。子要素の配置は、justify-contentにflex-start,flex-end,center,space-between,space-aroundを使用して指定することができます。

No項目justify-content の値配置
1左寄せflex-startitem1 item2 item3 item4 item5--------------
2右寄せflex-end--------------item1 item2 item3 item4 item5
3中央揃えcenter-------item1 item2 item3 item4 item5-------
4両端均等揃えspace-betweenitem1----item2----item3----item4----item5
5均等揃えspace-around---item1---item2---item3---item4---item5---

Logo コンポーネントの作成

ブログ名とリンク先にブログ説明のリンクを指定しています。ブログの説明記事は、/content/articles/ja/about.md に登録しています。/blog/about->/pages/blog/_slug.vue->/componetns/Article.vue->/content/articles/ja/about.md のような流れになります。

/components/Logo.vue
<template>
  <div>
    <nuxt-link to="/blog/about">akibo.i Blog</nuxt-link>
  </div>
</template>

index!

メニューは、Menus オブジェクトからメニューオブジェクトを順番に取り出しオブジェクトのリンク、アイコン、テキストを設定するシンプルなものです。

/components/Menu.vue
<template>
  <div>
    <nav>
      <ul class="global-menu">
        <div v-for="menu of menus" :key="menu.link">
          <li>
            <nuxt-link :to="menu.link"> <span :class="menu.icon"></span>{{ menu.text }} </nuxt-link>
          </li>
        </div>
      </ul>
    </nav>
  </div>
</template>

Mnue オブジェクトのリンクには、新着には、ルートページの index.vue が設定されており、それ以外は、/search/タグ名を設定します。これにより各メニューはタグに応じた記事一覧を表示するようにしています。

スクリプトには、メニューオブジェクトを設定しています。

/components/Menu.vue
    <script lang="ts">
    import { defineComponent, reactive, computed } from 'nuxt-composition-api'
     type Menu = {
       link: string
       icon: string
       text: string
    }
    export default defineComponent({
      setup() {
        const state = reactive<{
        menus: Menu[]
      }>({
        menus: [
         {
            link: '/',
            icon: 'fas fa-home',
            text: 'home',
          },
          {
            link: '/search/server',
            icon: 'fas fa-server',
            text: 'server',
          },
          {
            link: '/search/network',
            icon: 'fas fa-network-wired',
            text: 'network',
          },
          {
            link: '/search/nuxt',
            icon: 'fas fa-globe',
            text: 'nuxt',
          },
          {
            link: '/search/appliances',
            icon: 'fas fa-icons',
            text: 'appliances',
          },
          {
            link: '/search/etc',
            icon: 'fas fa-mortar-pestle',
            text: 'etc.',
          },
        ],
      })
      const menus = computed(() => state.menus)
      return { menus }
    },
    })
    </script>

アイコンには、Font Awesome を利用したいと思いますので、Font Awesome のアイコンのクラス名を指定します。

Tip Font Awesomeを利用するためには、nuxt.config.jsファイルのhead属性の中にFont Awesomeのスクリプトを記載します。従来のcssリンク方式であればhea属性のlinkに設定します。設定に必要なkit codeは、Font Awesomeサイトにログインして確認します。

/nuxt.config.js
     :
    head: {
     :
     script: [
       {
         src: 'https://kit.fontawesome.com/xxxx.js',←xxxxにkit codeを設定する。
         crossorigin: 'anonymous',
       },
     ],
     link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
    },
      :

最後に体裁を整えるためにスタイルシートを追加します。

/components/Menu.vue
    <style>
    .global-menu {
    align-items: center;
    display: flex;
    padding: 0 0.5rem;
    }
    .global-menu li {
    list-style: none;
    padding: 0 0.5rem;
    }
    </style>

メニューリンク先のページを作成

メニューリンク先/search/タグから該当するタグの記事を一覧表示するためにベージを作成していきます。やり方は index.vue の記事一覧と同じ方法となります。/pages/search/_slug.vue にファイルを作成します。今は Articles コンポーネントはタグ検索には対応していないので、Articles コンボーネントがタグ検索に対応したのちに設定していきたいと思います。今回はどれも同じ記事一覧となります。

/pages/search/_slug.vue
    <template>
      <Articles :target="target" :img="img" />
    </template>
    <script lang="ts">
      import { defineComponent } from 'nuxt-composition-api'
      export default defineComponent({
        setup() {
        const target = 'articles'
        const img = '/images/blog01.webp'
        return { target, img }
        },
      })
    </script>

ヘッダーを固定表示にする。

記事をスクロールしてもヘッダーは固定表示にして記事はヘッダーの下にするようにしたいと思います。合わせて default.vue に定義していた header のスタイルシートを変えていきます。

/layout/default.vue
.header {
  background: #fff;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 0 3px 0 #999;
  padding: 0.8rem;
  font-size: 0.8rem;
}

Tip ヘッダ要素を固定にしてその他の要素はスクロールしてヘッダの下を潜らせるには、ヘッダー要素にposition:stickyを設定します。またヘッダを一番上に表示させるためにz-indexを他の要素より大きい数字を設定します。

ヘッダが表示されれば完成です。次回は、言語切替に挑戦したいと思います。

index!