【Vue.js】リアクティブな検索機能を実装する方法

「リアクティブな検索機能をvueで実装したい」
「複数の値をdataに格納したけど、できればフロントで検索をかけて処理したい」
とお考えの方にコピペで完結する記事です。
デモはこちら。


https://stackblitz.com/edit/vue-ktxedd?file=src/components/Search.vue

# はじめに
多階層の配列にアクセスするには、１つのデータ郡それぞれを個別にみてkeyによって判別します。
デモではそれぞれの配列にあるnameというkeyと検索値が正規表現で部分一致な状態で検索することを想定しています。

# 検索機能を実装
検索にあたって下準備ですが、最初にaxiosなどでapiから取得したデータをプロパティ名が異なる２つに格納しましょう。
今回だとchat_usersとtemp_chat_usersですね。


```vuejs
<script>

export default {
  data(){
      return{
          chat_users:[
              {
                  id:1,
                  name:'たなか美穂',
                  message:'ありがとう...',
                  user_img:'woman2.png',
                  chat_id:10
              },
              {
                  id:2,
                  name:'みたか宗治',
                  message:'ありがとう！...',
                  user_img:'man.png',
                  chat_id:11
              },
              {
                  id:3,
                  name:'東なるみ',
                  message:'うーん。。...',
                  user_img:'woman.png',
                  chat_id:12
              },
          ],
          temp_chat_users:[
              {
                  id:1,
                  name:'たなか美穂',
                  message:'ありがとう...',
                  user_img:'woman2.png',
                  chat_id:10
              },
              {
                  id:2,
                  name:'みたか宗治',
                  message:'ありがとう！...',
                  user_img:'man.png',
                  chat_id:11
              },
              {
                  id:3,
                  name:'東なるみ',
                  message:'うーん。。...',
                  user_img:'woman.png',
                  chat_id:12
              },
          ],
          chat_id:'',
          search_list:[],
          user_sidebar_height: 500,
          search_user:''
      }
  },

.
.
.
</script>
```

検索ボックスにはv-modelと@input="searchUser"をつけて検索値を監視します。

```vuejs
<div id="search_user_box" class="mb-1 p-2 bg-white flex">
    　　　　　　<p>名前検索</p>
        <input v-model="search_user" @input="searchUser" class="p-1 w-10/12 border border-gray-300 focus:border-2 focus:outline-none focus:border-blue-500" type="text" >
    </div>
```

検索値を監視し、データにあるkeyの値と照合をかけます。

```vuejs
<script>

export default {
  .
  .
  .
  methods:{
      searchUser(){
          if(this.search_user){
              var serach_text = new RegExp(this.search_user + '(.*?)', 'g');
              const callback = (user) => user.name.match(serach_text);
              var list = JSON.parse(JSON.stringify(this.temp_chat_users)).filter( user => callback(user));
              this.chat_users = list;
          } else {
              this.chat_users = this.temp_chat_users;
          }
      },
  },
}
</script>

```

デフォルトで表示しているのは```chat_users```にあるデータですが、検索をかけたタイミングで```temp_chat_users```からデータを参照してmatchしたもののみ```var list```に入れて```this.chat_users = list;```とすることで置き換えができます。こうすることでデフォルトで表示したデータを失うことなく、裏にあるデータで常に置き換えるような仕組みがつくれます。

また、```var serach_text = new RegExp(this.search_user + '(.*?)', 'g');```では正規表現でマッチするもの全てとしています。```const callback = (user) => user.name.match(serach_text);```でmatchする条件を```serach_text```として処理を行い、filter()で配列にあるデータを個別に参照してcallbackで照合をかけます。
こうすることで、
filter()で個別に参照->callbackでmatch処理->正規表現で該当する全てを返す、
という流れをフロントで構築できます。

あとは値をthis.chat_usersに置き換えることでマッチしたもののみが表示されます。
今回は割愛していますが、
返り値がnull、lengthで0の場合「データがありませんでした。」を返す処理もif分岐でできますね。

検索値がない場合はデフォルトの状態が望ましいので、elseで``` this.chat_users = this.temp_chat_users;```としています。

## まとめ
今回は検索処理を実装しました。
プロパティのもつ値をフロントでかぎりなく処理できるなら有用で夢が広がりますよね。
次回は他コンポーネントと連携して親->子、子→親関係を全体的に反映できる方法を紹介したいと思います。