Vue.jsにおけるtemplate内での変数定義
★ネタです
ループなどでIDからユーザー情報を参照して、情報を表示するような実装がよくあります。
基本的には、次のように参照のたびに関数などを実行して情報を得るようにするかと思います。
code:vue
dl(v-for="id in selectdUserIdList")
dt 氏名
dd {{ getUser(id).name }}
dt 年齢
dd {{ getUser(id).age }}
しかし、これではプロパティの数だけ関数が実行されて効率がよくありません。
そこで、次のように関数の結果を変数へ保存して、使い回すようにしてみましょう。
code:vue
dl(
v-for="id in selectdUserIdList"
:set="user = getUser(id)"
)
dt 氏名
dd {{ user.name }}
dt 年齢
dd {{ user.age }}
:setプロパティは存在しないプロパティで、代入を実行させるためだけに定義しています。
これで、関数の実行は1度きりになり、実行数を減らすことができます。
めでたし。
ではない。
一見、めっちゃ便利やんけ!と思うTipsですが、Vueにおける変数のスコープを考えてみましょう。
VueのテンプレートにおけるglobalThisはコンポーネントインスタンスのthisを指します。
つまるところ、先程のBeforeのコードは
code:vue
dl(
v-for="id in this.selectdUserIdList"
:set="this.user = this.getUser(id)"
)
のように、コンポーネントインスタンスにプロパティを定義してしまっています。
そのため、定義されたuserはdl以下のみならず、コンポーネントのあらゆるところで使用できます。
また、例えば、
code:vue
dl(
v-for="id in users"
:set="users = getUser(id)"
)
とかしてしまうと、ループの最中にusersが変更されるため2周目から代入された値がループに使用されます。
数値を再代入したりするとレンダリングの無限ループが発生するので注意が必要です。
code:vue
div(v-for="v in values" :set="values = v") // 無限ループが発生する
scoped: {}みたいなDataを定義して、その値のみを変更するみたいな運用ルールをちゃんと決めれば使えないことはないと思いますが、こんなんみかけたら絶対レビューでツッコむ。
おわりに
template内でデータの取得をキャッシュしたい場合は、おとなしくコンポーネント化しよう。
onuma.icon面白いですね!
自分も変数キャッシュできないかなぁってずっと思っていたのですが、やっぱり無理そうなんですね。。。
👍 onuma onuma.icon がいいねしました on 2020/5/11