# モバイルのUIにVue InstantSeatchを入れた

先日このブログ(vuepressで出来ている)にDocSearchを導入したのだけれど、モバイルのUIは検索が思うようにトリガーされなくて、せっかくなのでVue InstantSearchを導入することにした。 (そのうちデスクトップ版というか、ブラウザの幅が広い版というか、、の方もVue InstantSearchに置き換えていきたいな、と)

# MobileHeader.vue を変更

MobileHeader.vueがケータイ用の表示を担っている部分で、今回はここに InstantSearch というのを突っ込むことでよしなにやれるようにしてみました👇

<template>
  <div id="mobile-header">
    <div class="mobile-header-bar">
      <div class="mobile-header-title">
        <NavLink
          link="/"
          class="mobile-home-link"
        >{{ $site.title }}
        </NavLink>
        <InstantSearch/> 👈👈ココ
        <component :is="isOpen ? 'XIcon' : 'MenuIcon'" @click="$emit('toggle-sidebar')"/>
      </div>
      <div class="mobile-menu-wrapper" v-bind:class="{ open: isOpen }">
        <hr class="menu-divider"/>
        <ul class="mobile-nav" v-if="$themeConfig.nav">
          <li class="mobile-nav-item" v-for="item in $themeConfig.nav">
            <NavLink :link="item.link">{{ item.text }}</NavLink>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

これを行うためにはScriptで👇をやってあげる必要があって、それようにInstantSearch.vueというファイルを作ってその中でホゲホゲすることにしました。

import InstantSearch from './InstantSearch.vue'
〜略〜
  export default {
    〜略〜
    components: {
      InstantSearch, 👈👈
      MenuIcon,
      XIcon
    },
}

# InstantSearch.vue を作った

MobileHeader.vueの中でやってしまっても良かったのかもしれないけど、そうすると今後デスクトップ版の時にコードが重複するのも嫌だなぁということで。 っていうか、すいません、、まだモノとして出来上がってない、、というかais-hitsの中をちゃんとしなくては、という…mm

<template>
  <div class="instantsearch">
  <client-only>
    <ais-instant-search index-name="yoshida.red" :search-client="searchClient" >
      <ais-search-box placeholder="blog" />
      <ais-powered-by />
      <ais-hits>
          <ul slot-scope="{ items }">
            <li v-for="item in items" :key="item.objectID">
              {{ item.anchor }}
            </li>
          </ul>
      </ais-hits>
    </ais-instant-search>
  </client-only>
  </div>
</template>

Scriptの中は↓こんな感じで、先日他のブログでも書いた、デフォルトではクエリを投げずに文字が入力された時だけ〜という実装にしています。(hitsを空にして、nbHitsとかnbPagesもゼロに。クエリ投げないのでprocessingTimeMSもゼロよ、と)

<script>
  import algoliasearch from 'algoliasearch/lite';
  import 'instantsearch.css/themes/algolia-min.css';
  
  const algoliaClient = algoliasearch(
    'APPID',
    'Search only API Key'
  );

  const searchClient = {
    search(requests) {
      if (requests.every(({ params }) => !params.query)) {
        return Promise.resolve({
          results: requests.map(() => ({
            hits: [],
            nbHits: 0,
            nbPages: 0,
            processingTimeMS: 0,
          })),
        });
      }
      return algoliaClient.search(requests);
    },
  };

  export default {
    data() {
      return {
        searchClient,
      };
    },
  };
</script>

で、ビルドする時に "Error: You are using server side rendering with <ais-instant-search> instead of <ais-instant-search-ssr>" とか言われてヒヨったのですが、templateのところを見ていただくと分かるように、"<client-only>"を付けて上げてココはクライアントでしか動かない旨を明示して上げましたよ、と。(ググったらno ssrっていうタグもあったのですが、それでは狙った通りの動作にはなりませんでした…)

でもって、そもそもVue InstantSearchを動かすのにどのJavaScriptに設定すれば、、っていうのはvuepressだとenhanceApp.jsっていうのがあって、そこに👇のように。

import InstantSearch from 'vue-instantsearch'

export default ({
  Vue, // the version of Vue being used in the VuePress app
  options, // the options for the root Vue instance
  router, // the router instance for the app
  siteData // site metadata
}) => {
  Vue.use(InstantSearch)

# そんなこんなで、、

👇こんな風になりました。クリックも出来ないし我ながら酷いのですが、とりあえず出すことが重要なのかもしれないので、pushだけさせていただきました…。近日中にちゃんとします。笑

mobile

っていうか、こうやって好き勝手あーだこーだしてるの楽しいなぁ。プラモデルとかだったら外からみたらイケてないの分かってしまうけど、趣味のソフトウェアならどれだけ中身がアレでも、、、。そして、得てしてこういうのって、オリャって捨ててしまいがちではあると思うんだけど、Github上でスクリプトとブログの投稿がまとめて管理されてるので、後からちゃんと昔の実装も追えてナイスでございます。

このエントリーをはてなブックマークに追加

Algolia検索からの流入のみConversionボタン表示