Help us understand the problem. What is going on with this article?

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

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

インクリメンタルサーチ(英語: 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;
}

8grp
【フリーランスITエンジニア向けの案件・お仕事の求人サイト「ENGER」運営】高単価 / 高契約更新率 ↓URLからお気軽にお問い合わせください
https://freelance.enger.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした