山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

【Vue】おれおれチュートリアル Ⅵ


第6弾です。前回までの記事はこちら。
【Vue】おれおれチュートリアル Ⅰ - 山崎屋の技術メモ
【Vue】おれおれチュートリアル Ⅱ - 山崎屋の技術メモ
【Vue】おれおれチュートリアル Ⅲ - 山崎屋の技術メモ
【Vue】おれおれチュートリアル Ⅳ - 山崎屋の技術メモ
【Vue】おれおれチュートリアル Ⅴ - 山崎屋の技術メモ

いまの画面がこのような感じです。
f:id:yyama1556:20181008094751p:plain

今回は簡単な機能追加を2つ行います。
 

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

  • 作者: 川口和也,喜多啓介,野田陽平,手島拓也,片山真也
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/09/22
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る
基礎から学ぶ Vue.js

基礎から学ぶ Vue.js


画面起動時にテキストボックスにフォーカスをあてる

画面起動時にすぐタスクの入力ができるようにテキストボックスに自動でフォーカスがあたるようにします。

Vue の「インスタンスライフサイクルフック」という機能を利用します。
公式ページ

フックできるライフサイクルは以下の種類があります。

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestroy
  • destroyed

このページで各サイクルの概要が説明されています。
Vue.jsのライフサイクルメモ - Qiita

今回は DOM にアクセスする必要があるので mounted でフックするのがよさそうです。

まず、Vue のコンポーネントから DOM を操作しやすいようにテキストボックスに ref 属性を付与します。こうすることによって JavaScript から「this.$refs.new_task」で DOM にアクセスできるようになります。

変更前:

        <el-input class="task-input" placeholder="追加するタスクを入力してください。" v-model="newTask" @keydown.enter.native="addTask"></el-input>


変更後:

        <el-input ref="new_task" class="task-input" placeholder="追加するタスクを入力してください。" v-model="newTask" @keydown.enter.native="addTask"></el-input>



Todo.vue の script タグ methods の後ろに mounted を追加します。

    mounted: function() {
        this.$refs.new_task.focus()
    } 



これで画面起動時にテキストボックスがフォーカスされるようになりました。
f:id:yyama1556:20181008104835p:plain
 
 

タスク達成後、元に戻す機能追加

現状、達成ボタンを押すと文字列に取り消し線が入りますが、元に戻す方法がありません。

なので一度、達成ボタンを押すとボタンの文字列が「戻す」に変わり、その「戻す」を押すと文字列の取り消し線が消えて、ボタンの文字列が「達成」に戻るよう機能を追加します。

Todo.vueの HTML テンプレート内の達成ボタンの行を書き換えます。

もう一つ「戻る」ボタンを追加し、達成・未達成の状態により達成ボタンと戻るボタンの表示を切り替えます。

判定には v-if を使います。式を評価し true であれば表示し false であれば表示されません。

変更前:

<el-button @click="scope.row.isComplete=true" type="primary" plain size="small">達成</el-button>


変更後:

<el-button @click="scope.row.isComplete=true" type="primary" plain size="small" v-if="!scope.row.isComplete">達成</el-button>
<el-button @click="scope.row.isComplete=false" type="primary" plain size="small" v-if="scope.row.isComplete">戻す</el-button>



これで一度達成したタスクを元に戻す機能ができました。
f:id:yyama1556:20181008165039p:plain
 
 

まとめ

では、いつものとおり、Todo.vue の今の時点の全量を載せておきます。

<template>
    <div>
        <h1>Todo List</h1>
        <el-input ref="new_task" class="task-input" placeholder="追加するタスクを入力してください。" v-model="newTask" @keydown.enter.native="addTask"></el-input>
        <el-button type="primary" plain @click="addTask">追加</el-button>
        <el-table
            :data="list"
            stripe
            class="list">
            <el-table-column style="padding: 8px">
                <template slot-scope="scope">
                    <span :class="{ complete: scope.row.isComplete }">{{ scope.row.value }}</span>
                </template>
            </el-table-column>
            <el-table-column>
                <template slot-scope="scope">
                    <el-button @click="scope.row.isComplete=true" type="primary" plain size="small" v-if="!scope.row.isComplete">達成</el-button>
                    <el-button @click="scope.row.isComplete=false" type="primary" plain size="small" v-if="scope.row.isComplete">戻す</el-button>
                    <el-button @click="deleteTask(scope.row)" type="danger" plain size="small">削除</el-button>
                </template>
            </el-table-column>
        </el-table>
    </div>
</template>
    
<script>
export default {
    data() {
        return {
            list: [
               { id:1, value: "たまご買う", isComplete: false }, 
               { id:2, value: "図書館に本を返す", isComplete: false },
               { id:3, value: "宅急便を受け取る", isComplete: false }
            ],
            newTask: "",
            nextId: 4
        }
    },
    methods: {
        addTask() {
            if(!this.newTask.trim()) {
                return
            }
            this.list.push({
                id: this.nextId++,
                value: this.newTask,
                isComplete: false 
            })
            this.newTask = ""
        },
        deleteTask(obj) {
            this.list = this.list.filter(e => e !== obj)
        }
    },
    mounted: function() {
        this.$refs.new_task.focus()
    } 
}
</script>

<style scoped>
.list {
    width: 80%;
    margin: auto;
    text-align: left;
}
.complete {
    text-decoration: line-through;
}
h1 {
    position: relative;
    line-height: 1.4;
}
h1:before { 
    font-family: "Font Awesome 5 Free";
    content: "\f00c";
    font-size: 0.7em;
    left: 0;
    top: 0;
    color: #5ab9ff;
}
.task-input {
    width: 60%;
}
</style>

GitHub にはここまでのソースを oreore6 というタグで公開してあります。
GitHub - yyama694/ore-todo: 【vue 】おれおれチュートリアル

次回はこちら。
www.shookuro.com



それでは!

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

  • 作者: 川口和也,喜多啓介,野田陽平,手島拓也,片山真也
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/09/22
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る
基礎から学ぶ Vue.js

基礎から学ぶ Vue.js