前置き
検索機能の仕方をご紹介💫
ベースの検索と、
axiosで取得したデータを
inputに入力した値で
検索するパターンを記載していきます✍️
参考:
コピペでOK!Vue.jsでリアルタイム検索をつくる方法
.indexOf()で配列のindexが取得できないとき
Nuxt.js+Algoliaで全文検索可能なタスク管理アプリを実装するハンズオン!
【Vue.js】computedとmethodsを使った簡単な検索機能
簡単な検索機能
ポイント
computed
data
の値に
何かしらの処理を行えます。
indexOf(string)
指定されたString
が
最初に現れたインデックスを返します。
値がなければ-1を返します。
今回はkeyword
を指定しているのでinput
に入力した値があれば
それを返すようにしています🧸
コード
主にこちらのコードを使用しています。
コピペでOK!Vue.jsでリアルタイム検索をつくる方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
<template> <div class="page"> <input type="text" v-model="keyword"> <ul> <li v-for="(user, index) in filteredUsers" :key="index" > {{ user.id }} {{ user.name }} {{ user.email }} </li> </ul> </div> </template> <script> export default { data () { return { keyword: "", users: [ { id: 1, name: '鈴木太郎', email: 'suzukitaro@example.com' }, { id: 2, name: '佐藤二郎', email: 'satoujiro@example.com' }, { id: 3, name: '田中三郎', email: 'tanakasaburo@example.com' }, { id: 4, name: '山本四郎', email: 'yamamotoshiro@example.com' }, { id:5, name: '高橋五郎', email: 'takahashigoro@example.com' }, ] } }, computed: { filteredUsers () { let users = [] // this.usersはデータ内のusers, 5個あるので5回繰り返す for(let i = 0; i < this.users.length; i++) { let user = this.users[i]; if(user.name.indexOf(this.keyword) !== -1 || user.email.indexOf(this.keyword) !== -1) { users.push(user); } } return users; } }, } </script> <style lang="scss" scoped> .page { padding: 20px; > input { border: 1px solid pink; } > .link { display: block; text-decoration: none; } } </style> |
filterに変更してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<template> <div class="page"> <input type="text" v-model="keyword"> <ul> <li v-for="(user, index) in filteredUsers" :key="index" > {{ user.id }} {{ user.name }} {{ user.email }} </li> </ul> </div> </template> <script> export default { data () { return { keyword: "", users: [ { id: 1, name: '鈴木太郎', email: 'suzukitaro@example.com' }, { id: 2, name: '佐藤二郎', email: 'satoujiro@example.com' }, { id: 3, name: '田中三郎', email: 'tanakasaburo@example.com' }, { id: 4, name: '山本四郎', email: 'yamamotoshiro@example.com' }, { id:5, name: '高橋五郎', email: 'takahashigoro@example.com' }, ] } }, computed: { filteredUsers () { return this.users.filter((user)=> { console.log(user) return user.name.indexOf(this.keyword) > -1 }) } }, } </script> |
indexOfはStringのみなので…
id
を指定して数字をつけてもString
でなければ検索できません。
配列にすればOKだったりします。
.indexOf()で配列のindexが取得できないとき
ただ、配列でindex
取得するとなると
0から始まるのがなんかモヤッとするので
文字列にしちゃうのが早いかも。
そうするとNumberで管理ができなくなって
不便ということもあるし、
そもそも数字で検索しなくて良い、
となるので不要かなと思いました💡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<script> export default { data () { return { keyword: "", users: [ { id: "1", name: '鈴木太郎', email: 'suzukitaro@example.com' }, { id: "2", name: '佐藤二郎', email: 'satoujiro@example.com' }, { id: "3", name: '田中三郎', email: 'tanakasaburo@example.com' }, { id: "4", name: '山本四郎', email: 'yamamotoshiro@example.com' }, { id:"5", name: '高橋五郎', email: 'takahashigoro@example.com' }, ] } }, computed: { filteredUsers () { let users = [] for(let i = 0; i < this.users.length; i++) { let user = this.users[i]; if(user.name.indexOf(this.keyword) !== -1 || user.email.indexOf(this.keyword) !== -1 || user.id.indexOf(this.keyword) !== -1) { users.push(user); } } return users; } }, } </script> |
axiosで取得したJSONデータで検索
今回は使用しませんが、
Algoliaを使って実装するのも良さそうです。
Firebase Cloud Firestoreでも
使用できるみたいです💫
ベースのコード
まずはベース作り
取得・表示をして
検索用のinputを用意します🍀
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<template> <div class="page"> <input v-model="keyword"> <ul> <li v-for="(post, index) in posts" :key="index" > id: {{ post.id }}<br> title: {{ post.title }}<br> body: {{ post.body }}<br> </li> </ul> </div> </template> <script> export default { data () { return { keyword: '', } }, async asyncData ({ $axios }) { const posts = await $axios.$get('https://jsonplaceholder.typicode.com/posts') return { posts } }, } </script> <style lang="scss" scoped> .page { } </style> |
完成コード
getters
にどうやってfilter
をかけるのか確認👀
https://vuex.vuejs.org/ja/guide/getters.html
今回は①を採用しました。
見やすいようにtitle
からのみ検索にしています。
①コンポーネント内のcomputed
で
state
を直接呼び出してfilter
②Vuex
内のgetters
でfilter
ただ本来はstate
を直接呼び出すことはないので
もっと綺麗なコードにできるかもしれません。v-model
をVuex
に入れてしまえば良いのかも。
ここは今後試す必要がありそうです🤔💭
この辺りを参考にしています。
https://www.webopixel.net/javascript/1461.html
https://tenrakatsuno.com/programing-note/vue-js-search-vuex/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<template> <div class="page"> <input v-model="keyword"> <ul> <li v-for="(post, index) in posts" :key="index" > id: {{ post.id }}<br> title: {{ post.title }}<br> body: {{ post.body }}<br> </li> </ul> </div> </template> <script> export default { data () { return { keyword: '', } }, computed: { posts () { return this.$store.state.posts.filter((post)=> { return post.title.indexOf(this.keyword) > -1 }) }, }, async fetch ({ store, $axios }) { const posts = await $axios.$get('https://jsonplaceholder.typicode.com/posts') store.commit('setData', posts) }, } </script> <style lang="scss" scoped> .page { } </style> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export const state = () => ({ posts: [], }) export const getters = { posts: state => { return state.posts }, } export const mutations = { setData(state, data) { state.posts = data }, } |
ここに至るまで
computed
内で非同期通信できるのか試したもの。
サポートされていないようです。
Vue.jsのcomputedでのaxios通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<template> <div class="page"> <input v-model="keyword"> <ul> <li v-for="(post, index) in posts" :key="index" > id: {{ post.id }}<br> title: {{ post.title }}<br> body: {{ post.body }}<br> </li> </ul> </div> </template> <script> export default { data () { return { keyword: '', } }, computed: { posts () { const posts = $axios.$get('https://jsonplaceholder.typicode.com/posts') posts.filter(function (value) { return value.title == "ex" }) }, }, } </script> <style lang="scss" scoped> .page { } </style> |
では非同期通信をasyncData
内でやろうとしたものの、
取得してきたデータをreturn
で返して
それにcomputed
でfilter
をかける…となると
データが二重?になって喧嘩するので、
これはfetch
を使わねばならん!となりました。
⬇️fetchはreturnしない時に使用します。
【Nuxt.js】非同期通信まわりまとめ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<template> <div class="page"> <input v-model="keyword"> <ul> <li v-for="(post, index) in posts" :key="index" > id: {{ post.id }}<br> title: {{ post.title }}<br> body: {{ post.body }}<br> </li> </ul> </div> </template> <script> export default { data () { return { keyword: '', } }, computed: { posts () { return this.$store.getters['jsonData'] }, }, async fetch ({ store, $axios }) { const posts = await $axios.$get('https://jsonplaceholder.typicode.com/posts') store.commit('setData', posts) }, } </script> <style lang="scss" scoped> .page { } </style> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export const state = () => ({ jsonData: [], }) export const getters = { jsonData: state => { return state.jsonData }, } export const mutations = { setData(state, data) { state.jsonData = data }, } |
fetch
で取得したデータをstate
に入れて
それを取得してv-model
の値でfilter
をかける
一旦はそこで落ち着いたというわけです💫☝️
まとめ
state
の直接の呼び出しには
まだモヤッと感が残りますが、
やりたいこと自体は実装できました🙌✨