前置き
データの変更の監視ができる
監視プロパティのwatch💥👀
算出プロパティとの比較を中心に
解説していきます🍓🙋♀️
公式: https://jp.vuejs.org/v2/guide/computed.html
算出プロパティ VS 監視プロパティ
input
に入力したデータの変更を検知して
表示もそれに応じて変えてます💫
でもこの場合ならcomputed
使った方が早くない?🤷♀️
とVue公式も言っています。
じゃあwatch
いつ使うんだ!😡
というのは後述するので
まずは違いを見てみましょう👀⚡️
❌ watch
入力するinput
の値を
全てを監視するので
とっても面倒ですね、
ほぼ同じことを書きます✍️💦
⭕️ computed
fullName
の1つにまとまるので
スッキリします✨
⬇️computed
の解説記事はこちら
監視プロパティwatch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<template> <div> <input type="text" v-model="firstName"> <input type="text" v-model="lastName"> <p>{{ fullName }}</p> </div> </template> <script> export default { data () { return { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' } }, watch: { firstName (value) { this.fullName = value + '' + this.lastName }, lastName (value) { this.fullName = this.firstName + '' + value }, }, } </script> |
算出プロパティcomputed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<template> <div> <input type="text" v-model="firstName"> <input type="text" v-model="lastName"> <p>{{ fullName }}</p> </div> </template> <script> export default { data () { return { firstName: 'Foo', lastName: 'Bar', } }, computed: { fullName () { return this.firstName + '' + this.lastName } }, } </script> |
watchにしかできないこと
多くの場合は算出プロパティが適切だけどwatch
にしかできないこともあります🌟
APIを使ったり、処理の実行頻度を制限したり。
この場合では、
https://jp.vuejs.org/v2/guide/computed.htmlwatch
オプションを利用することで、非同期処理(API のアクセス)の実行や、処理をどのくらいの頻度で実行するかを制御したり、最終的な answer が取得できるまでは中間の状態にしておく、といったことが可能になっています。これらはいずれも算出プロパティでは実現できません。
解説
watch
watchの使い方はこちら。
オプションも使えますが、
今回は使わないので
最低限の基礎構文のみ
記載しています✍️
1 2 3 4 5 |
watch: { 変更を監視するプロパティ名を記述: function (変更後の値, 変更前の値) { ここに処理内容を記述 } } |
input
の値を監視し、
値が変わっている間のテキストを表示させ、debouncedGetAnswer()
を呼び出します。
公式: https://jp.vuejs.org/v2/api/#vm-watch
参考: https://www.e-loop.jp/knowledges/2/
created()
解説記事をご覧ください❤️👀
_.debounce(function, wait, [immediate])
イベント発火後、
指定秒数で同じイベントを発火させずに留める。
この場合は質問が入力されてから0.5秒後に実行。
最大で0.5秒に1回しか実行されません。
参考:
http://underscorejs.org/#debounce
https://qiita.com/akifo/items/4d715929934a458fb189
indexOf(string)
指定されたStringが
最初に現れたインデックスを返します。
値がなければ-1を返します。
今回は?を指定しているので
質問に?がなく-1を返す場合は
「?を入れてね」と言われます🧸
?がある場合は
Thinking...が表示されます。
参考: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
axios
yesnoAPIを使うのでaxios
🌟
1万回に1回maybeが
返されることもあるみたいです😄
yesnoAPI: https://yesno.wtf/#
⬇️axiosの解説記事はこちら
_.capitalize(string)
指定された文字の
先頭のみ大文字、
あとは小文字にします。
https://yesno.wtf/apiを見ると
yesかnoが表示されるので
先頭を大文字にするために
使用していますね💡
コード
lodashはグローバルなモジュールで
importの必要はないとあるけど
importしないとエラーに
なってしまいました。。。
参考: https://ja.nuxtjs.org/faq/webpack-plugins/
Error
ReferenceError: _ is not defined
でもimportすれば良いだけなので…!
これでしっかり動きます🌟🤗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<template> <div class="page"> <p>Ask a yes/no question:</p> <input v-model="question"> <p>{{ answer }}</p> </div> </template> <script> import _ from 'lodash' import axios from 'axios' export default { data () { return { question: '', answer: 'I cannot give you an answer until you ask a question!', } }, watch: { // この関数は question が変わるごとに実行されます。 question (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing...' this.debouncedGetAnswer() } }, created () { // _.debounce は特にコストの高い処理の実行を制御するための // lodash の関数です。この場合は、どのくらい頻繁に yesno.wtf/api // へのアクセスすべきかを制限するために、ユーザーの入力が完全に // 終わるのを待ってから ajax リクエストを実行しています。 // _.debounce (とその親戚である _.throttle ) についての詳細は // https://lodash.com/docs#debounce を見てください。 this.debouncedGetAnswer = _.debounce(this.getAnswer, 500) }, methods: { getAnswer: function () { if (this.question.indexOf('?') === -1) { this.answer = 'Questions usually contain a question mark. ;-)' return } this.answer = 'Thinking...' var vm = this axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function (error) { vm.answer = 'Error! Could not reach the API. ' + error }) }, }, } </script> |
まとめ
基本的には算出プロパティを使い、
ダメならwatch❗️👀
非同期通信など
少し複雑な処理が必要なら❗️watch👀
というように
実装したい内容に合わせて
使い分けましょう🎶🎷