Vue.jsを使ってブログにリアルタイム検索を実装してみた話

はいどーも人生の正解を検索したい無職です。
本日はVue.jsを使ってブログにリアルタイム検索を実装した話をしてみたいと思います。
具体的にどれやねんというと、制作物一覧につけてます。
「主な記事の検索」というやつですね(ちょっと下にいかないとないです)。
なおここで言う「リアルタイム」とは、「入力されたそばから結果が表示される」くらいの意味です(要はエンターキーを叩いてページ遷移しなくても結果が見れる)。

なぜリアルタイム検索か

先日『速習Vue.js』を読んだという記事を上げました。
せっかくVue.jsを学んだのですから、こりゃ何か作らな損だというわけで、思いついたのがブログの記事検索だったのですね。
とは言えブログ内の検索はWordPressに標準(かプラグイン? 忘れました)でついています。
これは恐らくデータベースにアクセスして結果を返しているのだと思うのですが、僕がやりたかったのは「文字を入力するとリアルタイムに検索結果を反映させる」タイプの検索機能でした。
Vue.jsのデータバインディングを使えば楽勝そうだなと思ったので、練習の成果がてら作ろうと決めたわけですね。

データを書き出す

検索するということは、ある程度の決まった構造が必要です。
僕のブログは例えば「よくわからんものシリーズ」の中に「Unity用のストップウォッチ」という記事があったり「ツクールMVでオンラインランキングを実装する」という記事があったりします。
また「プラグイン制作講座」という中に「まっさらなシーンを作る」という記事があったり「シーンに画像を表示する」という記事があったりします。
また、各親には簡単な説明を添えています。例えば「よくわからんものシリーズ」なら「実験とか勉強で作ったものとか。」です。
そこでクラス構造としては以下のようなものを考えました。

Genreのインスタンスに相当するのは「よくわからんものシリーズ」や「プラグイン制作講座」ですね。
これは特に問題ないかと思います。
で、Genreは複数のArticleのインスタンスを保持しています。
Articleのtitleとurlは特に問題ないでしょう。tagsも単に検索ようのタグですね。複数指定できるように配列にしています。
で、visibleです。これは「検索時にページを遷移させることなく、検索にヒットしたものだけを表示させるために使う」プロパティです。
詳しくは後ほど見ていきます。

データを作成する

さてデータ構造が決まりました。
JavaScirptではJSONでデータを扱うのが簡単ですから、上述したデータ構造に従ってJSONデータを作成する必要があります。
が、ここで問題が起きました。
僕のブログは結構適当なHTMLの書き方をしていたため、規則性がなかったのですw
つまり自動での抽出が困難でした。
そこで僕は手作業でJSONファイルを作ることになったのです……。
死ぬほど面倒でしたが、具体的にはこのようなコードになりました(本当にハイパークソです)。

HTML側を作成する

さて何はともあれJSONデータの作成ができました。
次はHTML側を作成していきます。もちろんVue.jsを利用していきます。
元のHTMLはある程度決まっていたため、それに沿ってVue.jsでいい感じに組み立てればOKですね。

ここで軽くチェックしたところ「WordPressで利用されている機能のせいで、出力されたHTMLが何か変になる」という問題が発生しました。
ググったところ、ダブルクォーテーションが勝手に置換されることがあったようです。
なのでhttps://qiita.com/takagi7293/items/4583917b0e95d9bb7704この記事を参考にfunctions.phpを変更し、勝手に置換されないようにしました。

ですがまだ問題がありました。
Wordpressのテンプレートで利用しているCSSの何かが影響し、検索結果が変になってしまうのですね(貼ったコードは修正済みVerです)。

問題は

の部分でした。
元のHTMLではこの次のspanタグの中にv-if="ar.visible"を書いていたのですが、これをやってしまうと、どうもデザインが崩れるようでした。
なのでarticleタグの中に移動させ、現在の形になり、問題は解消されました。

さてHTMLではvisibleなら表示、そうでなければ非表示としているだけです。
また、ジャンルの中にvisibleな要素が一つもなければジャンル自体を非表示にしています。

JavaScript側

さてHTMLを書いただけでは動きません。
JavaScriptもといVue.jsも書く必要があります(実際の開発ではHTMLとJavaScriptは平行してチマチマいじりながら作ってました)。
というわけでコードをドン。

一行目のjsonは、最初に作成したデータを渡しています(実際には変換済みの文字列を渡しているだけです)。
Vue.jsを使っている部分も特に難しいことはしていませんね。
各Genreクラスが保持するArticleの配列をfor-of構文でぶん回し、タイトルにヒットするか、タグにヒットしたらvisibleプロパティをtrueに、そうでなければfalseにしているだけです。
これで完成ですね。
実際の表示は制作物一覧を実際に見てもらうのが一番ですが、一応画像もペタリ。

課題

Vue.jsの練習として作ったのですが、意外と面白かったです。
ただ課題もあります。
Vue.jsはModelとViewを分離するために使うのだと思うのですが、現状のHTMLを見ればわかるように、明らかにロジックが食い込んでしまっています。
でもこれはVue.jsに元から用意されている書き方ですし、それほど複雑なことをやっているわけではないので仕方ないのかなあ……なんて思いました。
実際どうなんでしょうね。

JSONデータの出力方法も大きな課題ですねw
現状は何か記事を追加するたびにdataCreator.jsにデータを追加し、新たなjsonデータを作成しなければなりません。
これはぶっちゃけ超面倒です。
なんとかうまいことできたらなあ……とは思っているのですが、今のところ特に案はありませんw

終わりに

いかがでしたでしょーか。
Vue.jsを使えば、僕のようにいわゆるDOMの操作を全くしたことがない人間でも、一日勉強すれば簡単に検索機能が作れちゃいました(もちろんJavaScript自体の理解は前提としてありますが)。
これは画期的ですね。
引き続き勉強を続けて、もっと使いこなして行きたいと思いますよ。
自分のサイトを持つ頃にはCLIでどうのこうのにも挑戦したいなあ……。あとコンポーネントとかルーティングとか……(WodrPressとの相性がよくなさそうな気もしてますが)。
まだまだ勉強しなきゃいけないことはたくさんありそうですw

ほなそんな感じでまた。

フォローする