LoginSignup
0
0

More than 1 year has passed since last update.

【Vue】絞り込み検索を作る

Posted at

Vueを使ったWEBアプリで絞り込み検索を作りました。

GitHubはこちら

💎 概要

  • 条件を選択する検索バーcomponentと場所データを管理するstore.jsでやりとりをし、表示する場所データリストを変更する。
  • 検索バーcomponentでは、条件をstoreに伝えるだけでデータリストの操作に関与しない。

画面

絞り込み検索前
絞り込み検索前
絞り込み検索後
絞り込み検索後

環境

  • vue(2.6.14)
  • vuex(3.6.2)
  • vuetify(2.6.0)

💎 コード

検索バーのcomponent

FilteringBarComp.vue
<template>
    <v-form
        ref="form"
        class="form-container d-flex flex-column flex-md-row justify-md-space-between"
    >
        <div class="d-flex">
            <v-select
                class="select-area mx-2"
                v-model="selectedArea"
                :items="area"
                item-text="label"
                item_value="value"
                label="AREA"
                hint="エリアを選んでください"
                persistent-hint
            ></v-select>
            <v-select
                class="select-category mx-2"
                v-model="selectedCategory"
                :items="category"
                item-text="label"
                item_value="value"
                label="CATEGORY"
                hint="施設の種類を選んでください"
                persistent-hint
            ></v-select>
            <v-select
                class="select-member mx-2"
                v-model="selectedMember"
                :items="members"
                label="MEMBER"
                hint="メンバーを選んでください"
                persistent-hint
            ></v-select>
        </div>

        <div class="d-flex align-center">
            <v-btn
            outlined
            color="white"
            @click="filterPlaceList()"
            >絞り込む</v-btn>

            <v-btn
            class="ml-2"
            outlined
            color="white"
            @click="resetPlacesList()"
            >リセット</v-btn>

            <div
            class="result-text mx-3"
            >検索結果:{{ $store.state.displayingPlaceList.length }}</div>
        </div>
    </v-form>
</template>

<script>

export default {
    data: () => ({
        // 絞り込み検索の項目リスト(メンバー)
        members: [
            "S.Coups",
            "Jeonghan",
            "Joshua",
            "Jun",
            "Hoshi",
            "Wonwoo",
            "Woozi",
            "The8",
            "Mingyu",
            "Dokyeom",
            "Seungkwan",
            "Vernon",
            "Dino"
        ],
        // 絞り込み検索の項目リスト(場所)
        area: [
            { label: "東京エリア", value: "tokyo" },
            { label: "大阪エリア", value: "osaka" },
            { label: "名古屋エリア", value: "nagoya" }
        ],
        // 絞り込み検索の項目リスト(施設分類)
        category: [
            { label: "道端", value: "roadside" },
            { label: "飲食店", value: "restaurant" },
            { label: "美術館", value: "museum" },
            { label: "公園", value: "park" },
            { label: "", value: "mountain" },
            { label: "その他店", value: "others" },
        ],
        filteredList: [],
        selectedArea: null,
        selectedCategory: null,  
        selectedMember: null,
    }),
    computed: {
        placeList() { return this.$store.state.placeList },
    },
    methods: {
        // storeのexcuteFilter関数を呼び出す関数
        // 選択された条件は複数存在するのでオブジェクトで渡す
        filterPlaceList() {
            this.$store.dispatch('executeFilter', {
                area: this.selectedArea,
                category: this.selectedCategory,
                member: this.selectedMember
            })
        },
        // 絞り込み検索の条件をリセットする関数
        resetPlacesList() {
            this.$refs.form.reset();
            this.$store.commit('resetFilter');
        }
    }
}
</script>

store.js

store.js(関係部分のみ)
export default new Vuex.Store({
    state: {
        // 全ての場所データリストJSON
        placeList: placeList,
        // 表示する場所データリスト(default: placeList)
        displayingPlaceList: placeList,
    },
    getters: {
        // 絞り込みfilter(エリア)
        filterOfArea: (state) => (area) => {
            if (area == "tokyo") {
                return state.placeList.filter(place => place.id > 1000 && place.id < 1999);
            } else if (area == "osaka") {
                return state.placeList.filter(place => place.id > 2000 && place.id < 2999);
            } else if (area == "nagoya") {
                return state.placeList.filter(place => place.id > 3000 && place.id < 3999);
            }
        },
        // 絞り込みfilter(カテゴリー)
        filterOfCategory: (state) => (category) => {
            return state.placeList.filter(item => item.placeCategory == category);
        },
        // 絞り込みfilter(メンバー)
        filterOfMember: (state) => (member) => {
            return state.placeList.filter(item => item.members.includes(member));
        }
    },
    mutations: {
        // 絞り込み後の場所データリストを反映させる関数
        // 引数listで絞り込み後のデータリストを受け取り、displayingPlaceListに代入
        setFilteredList(state, list) {
            state.displayingPlaceList = list;
        },
        // 絞り込み検索のリセット関数
        resetFilter(state) {
            state.displayingPlaceList = state.placeList;
        }
    },
    actions: {
        // 絞り込み検索を行う本体関数
        // 選択された条件がある場合、filterに通す
        executeFilter({ commit }, { area, category, member }) {
            let resultArr = this.state.placeList;
    
            // もし条件が選択されている場合(引数でもらったオブジェクトに値がある場合)、filterを実行する
            if (area != null) {
               const resultAreaArr = this.getters.filterOfArea(area);
               resultArr = resultArr.filter(item => resultAreaArr.includes(item));
            }
            if (category != null) {
               const resultCategoryArr = this.getters.filterOfCategory(category);
               resultArr = resultArr.filter(item => resultCategoryArr.includes(item));
            }
            if (member != null) {
               const resultMemberArr = this.getters.filterOfMember(member);
               resultArr = resultArr.filter(item => resultMemberArr.includes(item));
            }
            commit('setFilteredList', resultArr);
     },
  }
})

💎 思ったこと

  • storeにこんなに関数を入れていいのか?
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0