ブレークポイントでDOMを生成しないようにする
Vue+Vuetifyで作っている以下のおもちゃの話。後でどこかにまとめて書くけど、とりあえずメモとして残す。
https://direboar.github.io/githubpage-test/dist/#/
ソースはこっち。
https://github.com/direboar/vue-vuetify-example/blob/master/src/components/SpellDetailDialog.vue
- モバイルとデスクトップで同じシングルファイル・コンポーネントを使って表示するようにしている。
- デスクトップでは、V-Datatableを使って一覧表示したい(ソートなどしたいため)
- モバイルでは、V-Datatableは見切れるので、V-Listを使って表示したい項目を絞って出したい
という画面要求を満たすために、モバイル用とデスクトップ用の一覧表示を完全に別に作り、hidden-{breakpoint}-{condition}を使って、ブレークポイントで必要な一覧を表示するように制御していました。が、一覧の絞りこみが結構重たく、モバイルで動かすとかなり重たい。
試しにデバッガでDOMをみてみると、当然だけどhidden-{breakpoint}-{condition}で非表示にした要素も、DOMとして生成されている。重たい一覧表示を二重にやってりゃそりゃ重いよね…と思い、以下のようにしてブレークポイントで不要な画面はDOMごと消すようにした。
まず、computedプロパティに、モバイルかどうかを判定するメソッドを定義。
computed: { isMobile() { const mobileBreakpoints = ["xs", "sm"]; return mobileBreakpoints.some(e => { return this.$vuetify.breakpoint.name === e; }); }
次に、v-ifを使用してモバイル/非モバイルで表示を切り替えるコンポーネントについて、非表示時はDOM生成自体を行わないように制御。
<!--デスクトップ--> <!--検索結果--> <v-data-table v-if="!isMobile" :headers="headers" :items="items" item-key="name" no-data-text="条件に一致する呪文がありません。"> <template slot="items" slot-scope="props"> <tr @click="clickCell(props.item)"> <td class="text-xs-left">{{ formatSpellName(props.item) }} </td> <td class="text-xs-left">{{ props.item.hoge }} {{ props.item.level}}</td> <td class="text-xs-left">{{ props.item.formatArray(props.item.components,components) }}</td> <td class="text-xs-left nowrap">{{ props.item.casting_time }}</td> <td class="text-xs-left">{{ props.item.formatDuration }}</td> <td class="text-xs-left">{{ props.item.range }}</td> <td class="text-xs-left"> <v-icon>add</v-icon> </td> </tr> </template> </v-data-table> <!--モバイル--> <!--検索結果--> <v-list v-if="isMobile" dense two-line> <v-data-iterator content-tag="v-card" :items="items"> <v-list-tile avatar slot="item" slot-scope="props" @click="clickCell(props.item)"> <v-list-tile-content> <v-list-tile-title>{{props.item.name}} </v-list-tile-title> <v-list-tile-sub-title>{{props.item.level}}/{{props.item.format(props.item.school,schools)}}/{{props.item.formatArray(props.item.components,components)}}</v-list-tile-sub-title> </v-list-tile-content> <v-list-tile-avatar> <v-icon>add</v-icon> </v-list-tile-avatar> </v-list-tile> </v-data-iterator> </v-list>
こんな感じで調整したら、モバイルの糞思い処理が、やや重いくらいに改善した。
根本解決にはなってないんですけどね。複数の検索条件を設定し、条件変更都度一覧の絞り込みをcomputedプロパティで行うようにしているだけなんですが…何が悪いんだろ?