クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【Vue.js】localStorageと連携したTodoリストを読み解く(JS編-3)

Vue.jsシリーズ、公式サイトのサンプルにあったlocalStorageと連携したTodoリストのコードを読み解く。前回はJS編その2としてVueインスタンス以外のコードを見ていきました。localStorageを読み込む箇所も見受けられました。今回がラスト。Vueインスタンス本体を見ていきます。それではいきましょう!

【目次】

※前回:【Vue.js】localStorageと連携したTodoリストを読み解く(JS編-2) - クモのようにコツコツと

Todoリスト完成品とVueインスタンス全体像

Todoリスト完成品

See the Pen Vue de Localstarage by イイダリョウ (@i_ryo) on CodePen.

Vueインスタンスの全体像

// app Vue instance
var app = new Vue({
  // app initial state
  data: {
    //処理
  },

  // watch todos change for localStorage persistence
  watch: {
    //処理
  },

  // computed properties
  // http://vuejs.org/guide/computed.html
  computed: {
    //処理
  },

  filters: {
    //処理
  },

  // methods that implement data logic.
  // note there's no DOM manipulation here at all.
  methods: {
    //処理
  },

  // a custom directive to wait for the DOM to be updated
  // before focusing on the input field.
  // http://vuejs.org/guide/custom-directive.html
  directives: {
    //処理
  }
})

Vueインスタンス以外のJSコードについては「JS編-2」を参照。

※参考:【Vue.js】localStorageと連携したTodoリストを読み解く(JS編-2) - クモのようにコツコツと

Vueインスタンス詳細

Vueインスタンスの詳細を見ていく。

まず冒頭は変数appVueインスタンス作成。

// app Vue instance
var app = new Vue({
    //処理(中略)
})

一番最後の行の閉じ括弧までが一括り。この中に処理を書く。連想配列になっているのでキー(Vueオプション)になっている。キーごとにみていく。

dataオプション

一つ目はdataオプション。冒頭コメントの和訳。

アプリ初期状態

  // app initial state
  data: {
    todos: todoStorage.fetch(),
    newTodo: '',
    editedTodo: null,
    visibility: 'all'
  },
  • dataキーの値は連想配列
  • todosキーの値todoStoragefetch()
  • newTodoキーの値は空
  • editedTodoキーの値はnull
  • visibilityキーの値はall

データの初期値をいろいろ設定してある。todosキーの値に「JS編-2」のtodoStoragefetch()が出てきた。ここに取得されているlocalStrageの値をtodosに入れるわけだ!

newTodoは新しい予定と思われ初期は空。editedTodoは編集した予定と思われこれも空。

visibilityは「HTML、CSS編」にも「JS編-2」にも出てくるがタブメニューの部分。初期は「すべて」ということだ。

watchオプション

二つ目、watchオプション。

localStorageの持続性のためにタスクの変更を監視する

watchは監視プロパティ。何かを監視して、変化があったら処理を実行する。

※参考:【Vue.js】watch(監視プロパティ)で戦国時代クイズを作った - クモのようにコツコツと

 // watch todos change for localStorage persistence
  watch: {
    todos: {
      handler: function (todos) {
        todoStorage.save(todos)
      },
      deep: true
    }
  },
  • watchキーの値は連想配列
  • handlerキーの値は無名関数で引数はtodos
  • todoStoragesave()todosが入る
  • deepキーの値はtrue

todosの配列の値に変化があったらhandlerキーとdeepキーを実行。

handlerキーはtodostodoStoragesave()を実行。save()も「JS編-2」に出てきた。localStrageに保存。

deepキーの値はtrueに。これはオブジェクトの監視に必要なプロパティ

※参考:[https://qiita.com/Keitaro/items/8e3f8448d1a0fe281648:title]

computedオプション

三つ目、computedオプション。

計算プロパティ

computedは算出プロパティ。以前、割り勘アプリの記事で触れたように入力に対するリアルタイム処理。

※参考:【Vue.js】computed(算出プロパティ)で割り勘アプリを作る(おまけでこち亀アプリも) - クモのようにコツコツと

// computed properties
  // http://vuejs.org/guide/computed.html
  computed: {
    filteredTodos: function () {
      return filters[this.visibility](this.todos)
    },
    remaining: function () {
      return filters.active(this.todos).length
    },
    allDone: {
      get: function () {
        return this.remaining === 0
      },
      set: function (value) {
        this.todos.forEach(function (todo) {
          todo.completed = value
        })
      }
    }
  },
  • computedキーの値は連想配列
  • filteredTodosキーの値は無名関数
    そのfiltersvisibilityキーのtodosを返す
  • remainingキーの値は無名関数
    そのfiltersのアクティブなtodosの数を返す
  • allDoneキーの値は連想配列
    getキーの値は無名関数
    そのremainingの値を0かどうかの結果を返す setキーの値は無名関数で引数はValue
    そのtodosで配列ループを実行。実行する無名関数の引数はtodo
    todoのcompletedプロパティの値をvalue`に

filteredTodosは「HTML、CSS編」に出てきた。リストliタグをv-for属性でループする値todo in filteredTodosfiltersは次に登場するオプションでvisibilityはタブの状態なので、該当するタブのTodoを返す。

remainingも「HTML、CSS編」に出てきた。「○件完了」の表記部分。アクティブなタブのtodoの件数を返す。activeは「JS編-2」の変数filtersに出てきた。

allDoneも「HTML、CSS編」に出てきた。リスト入力欄の頭にある全選択の部分。値の取得(get)と値の変更(set)を設定。

※参考:Vue.jsでGet/Setの作成 【JavaScript フレームワーク入門】 - JavaScript勉強会

getthis.remainingが0かどうか確認。setではtodoをループですべて完了にする。

なお、===は型も含めた厳密な比較

※参考:JavaScript 忘れがちな === と == の違い - Qiita

filtersオプション

4つ目、filtersオプション。これには冒頭コメントがついてない。

filtersオプション、公式サイトによると

Vue.js では、一般的なテキストフォーマットを適用するために使用できるフィルタを定義できます。

※参考:フィルター — Vue.js

んん?なんだって?

フィルタはテキストを変換する処理を担っている

※参考:【Vue.js】フィルタについて解説 | とものブログ

なるほど。

 filters: {
    pluralize: function (n) {
      return n === 1 ? '件' : '件'
    }
  },
  • filtersキーの値は連想配列
  • pluralizeキーの値は無名関数で引数はn
  • n1がtrueならを、falseならを返す。

pluralizeは「HTML、CSS編」に出てきた。「○件完了」の「件」の単位部分。

?は三項演算子。

condition ? expr1 : expr2

condition が true の場合、演算子は expr1 の値を返します。そうでない場合は expr2 の値を返します。

※参考:条件 (三項) 演算子 - JavaScript | MDN

公式では単数形「item」と複数形「items」に分岐したが、今回はどちらも同じという値を返すように打ち変えた。

methodsオプション

五つ目、methodsオプション。

データロジックを実装するメソッド。  DOMの操作はまったくありません。

いつものように処理を書くオプション。

// methods that implement data logic.
  // note there's no DOM manipulation here at all.
  methods: {
    //処理(中略)
})
  • methodsキーの値は連想配列

この中にmethodsオプションの処理がいくつかのキーに分かれて書かれている。結構モリモリな内容なので、キーごとに見ていく。

addTodoキー

キー名は処理内容が想像つく名前になっている。addTodoキーはTodoの追加の処理が書かれている。

    addTodo: function () {
      var value = this.newTodo && this.newTodo.trim()
      if (!value) {
        return
      }
      this.todos.push({
        id: todoStorage.uid++,
        title: value,
        completed: false
      })
      this.newTodo = ''
    },
  • addTodoキーの値は無名関数
  • 変数valueはそのnewTodoかつそのnewTodo.trim()
  • もしvalueがtrueでなければ何も返さない
  • そのtodosの配列の末尾に下記の値を追加
    idキーにのtodoStorage.uidの数を1加算
    titleキーをvaluecompletedfalse
  • そのthis.newTodoの値を空に

addTodonewTodoは「HTML、CSS編」に出てきた。1行目の入力欄。newTodoは先ほどのdata:で初期状態は空。

&&!は論理演算子。&&はAND(=かつ)、!はNOT(=以外)。

※参考:論理演算子 - JavaScript | MDN

trim()は文字列の両端のスペースを削除。

※参考:String.prototype.trim() - JavaScript | MDN

push()は配列の末尾に値を追加

※参考:Array.prototype.push() - JavaScript | MDN

todoStorage.uidは「JS編-2」に出てきた。localStrageの件数。

titleは「HTML、CSS編」に出てきた。todoのタイトル部分。localStrageにも登録される。

completedは「HTML、CSS編」にも「JS編-2」にも出てくる、Todoの完了状態をlocalStrageに登録。

removeTodoキー

こちらはTodoの削除の処理

    removeTodo: function (todo) {
      this.todos.splice(this.todos.indexOf(todo), 1)
    },
  • removeTodoキーの値は無名関数で引数はtodo
  • そのtodosの配列からtodoを削除

removeTodoは「HTML、CSS編」に出てきた。バツ(×)ボタンの部分。

splice()は配列からの要素の追加や削除

※参考:Array.prototype.splice() - JavaScript | MDN

indexOf()は配列の値が何番目にあるかを返す

※参考:Array.prototype.indexOf() - JavaScript | MDN

editTodoキー

Todoの編集の処理

    editTodo: function (todo) {
      this.beforeEditCache = todo.title
      this.editedTodo = todo
    },
  • editTodoキーの値は無名関数で引数はtodo
  • そのbeforeEditCacheの値をtodo.title
  • そのeditedTodoの値をtodo

beforeEditCacheは他の場所と紐づいていないプロパティのようだが、名前から編集前の状態と思われる。編集時にここにtitleを入れている。

editedTodoは「HTML、CSS編」に出てきた。編集用のリスト. editにある。ここにtodoを入れている。

doneEditキー

編集の実行処理

    doneEdit: function (todo) {
      if (!this.editedTodo) {
        return
      }
      this.editedTodo = null
      todo.title = todo.title.trim()
      if (!todo.title) {
        this.removeTodo(todo)
      }
    },
  • doneEditキーの値は無名関数で引数はtodo
  • もしそのeditedTodoでなければ、何も返さない
  • そのeditedTodoの値を空null
  • todotitleの値をtodo.title.trim()
  • もしtodotitleがなければtodoの削除removeTodo()を実行

doneEditも「HTML、CSS編」の編集用のリスト. editに出てくる。 上のeditTodoキーと関連深い。editTodo実行後の入力欄からの削除の処理が書かれている。

cancelEditキー

編集キャンセルの処理

    cancelEdit: function (todo) {
      this.editedTodo = null
      todo.title = this.beforeEditCache
    },
  • cancelEditキーの値は無名関数で引数はtodo
  • そのeditedTodoの値を空null
  • todotitleの値をそのbeforeEditCache

cancelEditも「HTML、CSS編」の編集用のリスト. editに出てくる。編集をキャンセルしたときに元の状態に戻す処理が書かれている。

removeCompletedキー

Todoの完了および削除の処理

    removeCompleted: function () {
      this.todos = filters.active(this.todos)
    }
    }
  },
  • removeCompletedキーの値は無名関数
  • そのtodosの値をfiltersactive()に。引数はそのtodos

removeCompletedは「HTML、CSS編」に出てくる。「すべて削除」のボタン。active()に該当するtodosを入れるとアクティブが削除になるようだ。

directivesオプション

六つ目、directivesオプション。最後のオプション。

DOMが更新されるのを待つカスタムディレクティブ  入力フィールドに注目する前に

公式サイトによると

Vue.js 本体で出荷されたディレクティブの標準セットに加えて (v-model と v-show)、カスタムディレクティブ (custom directive) を登録することができます

※参考:カスタムディレクティブ — Vue.js

なるほど。directivesオプションによってHTML編に出てきたカスタムディレクティブを設定しているわけか。

  // a custom directive to wait for the DOM to be updated
  // before focusing on the input field.
  // http://vuejs.org/guide/custom-directive.html
  directives: {
    'todo-focus': function (el, binding) {
      if (binding.value) {
        el.focus()
      }
    }
  }
})
  • directivesキーの値は連想配列
  • todo-focusキーの値は無名関数で第1引数がel、第2引数がbinding
  • もしbindingvalueがあれば
    elfocus()メソッドを実行

todo-focusを設定し、HTML上ではv-を追加してv-todo-focusと書くことで紐づく。v-todo-focusHTML編の編集用のリスト. editに出てくる。

focus()はフォームのフォーカス状態を設定する関数。

※参考:JavaScript/フォーム/自動的にフォーカスを合わせる - TAG index

リストliの中で編集できるものをフォーカス状態にする。

最後に

f:id:idr_zz:20190804224758j:plain

ようやく最後までたどり着いた!知りたかったlocalStrageの部分はこんな位置関係でした。

  • JS編-2」の変数STORAGE_KEY、変数todoStorageがlocalStrageの設定。中に変数todosがある。
  • 本記事Vueインスタンス内のtodoStoragetodosへの処理がlocalStrageに紐づく。
  • HTML、CSS編」上のVue属性やマスタッシュタグのtodosが本記事Vueインスタンスと紐づく。

今回はボリューミーだったため、全体像をつかむのに時間がかかり、記事も4回に分かれました。しかしVue以外のJSの記法や関数もいろいろ入っていて勉強になった。それではまた!


※参考:Vue.jsの習得のためにやったことまとめ
qiita.com