先日書いた記事で、出来るだけtemplateで$emitした方が良いと書きました。
<template>
<dl>
<dt>名前入力</dt>
<dd>
<input
type="text"
@input="$emit('customEvent', hoge('hogehoge'))"
/>
</dd>
</dl>
</template>
こういう感じにemitは直接templateから指定して、引数からメソッドを呼んで必要に応じて成型した戻り値を親コンポーネントへ送ります。
みたいなことを書いたわけですが、$emit時に返す値がAPIの読み込みなどの非同期な場合に上手くいかない事がありました。
なのでそういう場合は
hoge(e){
axios.get('fuga', e).then(res => {
this.$emit('fuga', res.data)
})
}
みたいな感じに、イベントから呼び出した関数内でemitするパターンになってしまうのですが…。
async hoge(e){
const param = await axios.get('fuga', e).then(res => res.data)
// 実際にはここでparamの加工とかする
return param
}
とか言う感じでpromiseで返してあげると
<template>
<div id="app">
<SampleComponent @customEvent="fuga" />
</div>
</template>
<script>
export default {
components: {
SampleComponent
},
methods:{
fuga(e){
e.then(result => alert(result))
}
}
}
</script>
親側で受け取った際に、引数にPromiseオブジェクトで帰ってくるので、引数にthen
とか付けれました。
まぁ、よく考えれば、そりゃそうだろうって感じですが…。
さらにこんな感じにすると、もっといい感じに!?
<script>
export default {
components: {
SampleComponent
},
methods:{
async fuga(e){
alert(await e)
}
}
}
</script>
ちなみに、Promiseオブジェクトで送るのがなんか嫌でこう書いたら動くんですが、vue側でエラーを出してきます。
<button @click="hoge().then(res => $emit('hogehoge', res))">TEST2</button>
[Vue warn]: Property or method "then" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
こんな感じのエラーになりました。英語に疎いのでちょっと意味が…。
とまぁ、何の役にも立ちそうにない小話です。
できれば$emitがpromiseにも対応してくれればいいなぁと思った今日この頃です。