LoginSignup
2
3

More than 3 years have passed since last update.

Vue.js でインクリメンタルサーチ

Last updated at Posted at 2020-04-02

インクリメンタルサーチとは

インクリメンタルサーチ(英語: incremental search)は、アプリケーションにおける検索方法のひとつ。検索したい単語をすべて入力した上で検索するのではなく、入力のたびごとに即座に候補を表示させる

完成品

スクリーンショット 2020-04-02 22.40.28.png

スクリーンショット 2020-04-02 22.40.38.png

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>インクリメンタルサーチ</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="app">
        <!-- v-model を指定する -->
        <input type="text" placeholder="検索" v-model="search">

        <!-- sort とソート順選択欄を v-modelで結ぶ -->
        <select v-model="sort">
            <option value="">ソート無し</option>
            <option value="asc">昇順</option>
            <option value="desc">降順</option>
        </select>
<!-- v-for を使ったリストをアニメーションさせるためのコンポーネント <transition-group>key 属性を付ける必要がある -->
        <transition-group tag="ul">
            <!-- <li v-for="item in list">  listプロパティの値をv-forで回す -->
            <!-- fileterdListを表示 -->
            <li v-for="item in sortedList" v-bind:key="item.id">
                {{ item.text }}
            </li>
        </transition-group>
    </div>

    <script src="main.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>
</html>

JS


new Vue({
    el: "#app",
    data:{
        //入力フォームに入力された値を表すデータを定義
        search: '',
        //現在どの並び順でソートしているのかを表すデータ
        sort: '',
        //、次は検索対象のデータを定義
        list: [
            { id: 1, text: 'Python' },
            { id:2, text: 'Ruby'},
            { id:3, text: 'PHP'},
            { id:4, text: 'JavaScript'},
            { id:5, text: 'Java'},
            { id:6, text: 'Go'},
            { id:7, text: 'C'},
            { id:8, text: 'C#'},
            { id: 9, text: 'Rails' },
            { id:10, text: 'Django'},
            { id:11, text: 'MySQL'},
            { id:12, text: 'Vue.jst'},
            { id:13, text: 'react'},
            { id:14, text: 'Docker'},
            { id:15, text: 'unity'},
            { id:16, text: 'jQuery'}
        ]
    },
    computed: {
        //検索処理としてfileterdListを定義
        filteredList: function(){
//filter のコールバック関数内では引数に配列の各項目が渡され、返り値が true となった項目のみ出力
            return this.list.filter(function(item){
//ある文字列に他の文字列が含まれているかどうかを調べる時は indexOfを使用
//item.text 文字列に、this.search という文字列が含まれている時に、その文字列の場所を表す数値を返し、含まれていないときには -1 を返し
                return item.text.indexOf(this.search) > -1
            }, this)
        },

        //ソート後のデータを返す算出プロパティ sortedList
        sortedList: function(){
            var copy = this.filteredList.slice()

            if(this.sort === 'asc' ){
                //comparatorAsc メソッドをコールバックとして sort 関数に渡す
                return copy.sort(this.comparatorAsc)
            } else if(this.sort === 'desc') {
                //降順に並べ替えるためのコールバック関数は comparatorDesc
                return copy.sort(this.comparatorDesc)
            } else{
                return copy
            }
        }
    },
    methods:{
        comparatorAsc: function(itemA, itemB){
            if(itemA.text < itemB.text){
                return -1
            } else if(itemA > itemB.text){
                return 1
            } else{
                return 0
            }
        },

        comparatorDesc: function(){
            if(itemA.text > itemB.text){
                return -1
            } else if(itemA < itemB.text){
                return 1
            } else{
                return 0
            }
        },
    }

});

CSS


body{
    font-family: sans-serif;
}

input,
select{
    padding: 2px 8px;
    font-size: inherit;
    vertical-align: middle;
}

ul {
    position: relative;
    margin-top: 6px;
    padding: 0;
    width: 300px;
    list-style: none;
}

li{
    margin: 0;
    padding: 10px;
    border-bottom: 1px solid #ddd;
}

.v-move{
    transition: transform 300ms ease-out;
}

.v-enter-active {
    transition: 300ms;
}

.v-enter{
    opacity: 0;
}

.v-enter-to{
    opacity: 1;
}

.v-leave-active{
    transition: 300ms;
}

.v-leave{
    opacity: 1;
}

.v-leave-to{
    opacity: 0;
}

2
3
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
2
3