vue(nuxt)のcomputedとwatch覚書です。
目次
vue(nuxt)でcomputedの呼び出しタイミング【使い方】
computedの呼び出しタイミング
computed: {
test() {
console.log('test')
}
}
起動時に呼ばれますね。Html側で{{ test }}で呼び出しましょう。
{{ test }}
v-modelの呼び出し
computed: {
test: {
get() {
console.log('get')
return ''
},
set(val) {
console.log('set')
this.data = val
}
}
}
これだけでは起動時には呼ばれません。html側でこの場合testをv-modelで呼んであげましょう。
v-modelはcomputedだけではなくdataなどに関連付けても使えます。
set側でdataを入れてあげる形が多いです。setはinputの入力するたびに呼ばれます。
getはreturn必須です。エラーがでます。inputで使う場合、初期値になります。inputの値をいじってもgetは呼ばれませんが、this.dataをretuen側に返すとdataが書き換わった瞬間getが呼ばれます。そのgetを{{data}}みたいな感じで表示します。
computed: {
test: {
get() {
console.log('get')
return this.data
},
set(val) {
console.log('set')
this.data = val
}
}
}
if文で切り分けてthis.data = valが呼ばれないと、初回入力がクリアされるっぽいです。確実に呼ばれるにしましょう。
firebaseに登録時に呼ばれない
VueXを使っている場合、createdの書き忘れ。
created() {
this.$store.dispatch('data/bindData')
},
props渡しでcomputedが呼ばれない
わりと凡ミスという気がします。v-ifで{{test}}が囲まれていたとか、undefinedにもならないはず。
簡単なサンプルを作ったら配列渡しも問題なくできました。
pass: {
type: Array,
default: () => {}
},
computed: {
test() {
console.log('test', this.pass)
return this.pass
}
}
<button @click="add">ボタン</button>
<Child :pass="test" />
testに配列が入ったとき、computedが呼ばれます。
methods: {
add() {
console.log('addです。', this.test)
this.test = this.array
}
}
vue(nuxt)でcomputedの使い方【小ネタ】
computedとdata
computedとdataのどちらかに初期値が記載されていればOKです。
mapGettersなどから値を取得した場合、あえてcomputedに初期の処理を書いた方がいい場合もあります。
初回のみはdataに指定しcreateに記述すればOKです。v-bindをcomputedに関数化して記述すると複数回呼び出されて悩まされることもあります。
computedのthis
computedに限らず、thisを使うと、dataなどすべての値にアクセスできます。
computed: { test: { get() { this.name = 'vue-kun' // NG return this.name // OK }, set(val) { this.name = val // OK } } }
ただし、getの代入はダメです。
Unexpected side effect in "XXX" computed property
がでます。
computedのsetと表示変更
選択した際に表示を変える場合、次のように繋ぐのが便利ですね。
computed: { choice: { get() { }, set(val) { this.selected = val } } show() { const show = this.selected } }
this.selectedはもちろんmethodsなどでも取得できます。
computedからmethodsの呼び出し
computedからmethodsの呼び出しすることがあります。こちらは問題なくできます。
computed: { test() { this.addServerData(string) } }, methods: { addServerData(name) { this.name = name } }
methods先でreturnしたものをconstに代入してreturnはできます。あと、thisはうっかりとつけ忘れないようにしましょう。
ただ、watchで処理する場合もあります。
computedでfirebaseからデータを取得時にnull
computedでfirebaseからデータを取得時にnulがくる症状がでました。
とりあえず、以下のように応急処理しました。
computed: { ...mapGetters({ getData: 'data/getData' }), test: { get() { if (this.getData === null) { return null } } return this.getProfile.name }, set(val) {} } created() { this.$store.dispatch('data/bindData') },
初期化時と変更時に呼びだされますが、初期化時点ではnullがきてしまうようです。
computedとwatchの違いは戻り値
似ていますが、watchには戻り値がありません。そのためcomputedを使われる方が多いかもしれません。基本はcomputedです。
watchはapiの非同期通信などに使います。
computedの引数渡し
通常の方法では渡せません。返り値を関数にして渡します。
computed: {
getImg() {
return (num) => {
console.log('num', num)
}
}
}
if文で切り分けている場合、他もreturn () => {}で返さないといかないため忘れずに。
場合によってはmethodsに書くのも手です。
computedの学習なら
computedの学習なら、、udemyに良質な教材があります。vue、nuxt、firestoreなどのおすすめ教材をまとめました。
Computedのエラー
[Vue warn]: Computed property “” was assigned to but it has no setter.
[Vue warn]: Computed property "" was assigned to but it has no setter.
setterが必要なのにないですね。v-modelを使っているのにsetとgetの構成ではないということです。
error Unexpected asynchronous action in” ” computed property
error Unexpected asynchronous action in" " computed property
たぶんcomputedの中に書いちゃいけないコードが入っていますかね。一部を切り出してmethodsに移動したら消えました。そのmethodsをcomputedから呼び出しました。
watch
概要と呼び出しタイミング
watchはreturnが使えません。監視タイミングが変化したタイミングで呼ばれます。thisも使えないため、適当な変数を用意します。基本はcomputedを使いますが、非同期処理に使います。
初期化の発火
初期化のタイミングで発火したい場合は、immediate: trueを付与します。
watch: {
data: {
handler(val) {
this.data
},
immediate: true
}
}
watchが呼ばれない
監視するdataがobjectだった場合、deepのフラグが必要なようです。
watch: {
obj: {
handler: function(){
// 実行
},
deep: true
}
}
vueのライフサイクル(呼ばれる順番)
呼ばれる順番ですが、よく使うところだとcreated、mounted、watchの順番です。
- createdはDOM生成前
- mountedはDOM生成後(描画後、プラグインの初期化などを行う)
- watchは監視してひっかける感じ
詳細は公式で。
あれ?computedがない?
検証はしていませんが、こちらの記事をみました。
created、computed、mounted、watchの順番ですかね。
使い分けは初回読み込むだけの場合はcreatedを使う。
computedは何度も再計算が必要なもの。input系の要素に多い。
mountedはプラグインとか。
watchは非同期処理のもの。firebaseも他に書くとタイミングの都合でnullがくることがあるので、watchに書く場合もあり。
mounted内の値をcomputedのgetter()でつかうことはできません。
基本的なことでしたが参考になれば幸いです。
コメント