v-data-tableがv3.4.0でリリースされました。
あとは、v-calendarだけが残っているようです。→ Introduction to Labs — Vuetify
以前、Vuetify Labsので暫定対応しましたが、こちらにアップデートしたので、Vuetify2とVuetify Labsからの変更点をメモしておきます。
→ Vuetify Labsとv3-infinite-loadingでv-data-tableを暫定対応する
v-data-table -> Upgrade guide — Vuetify
- Vuetifyバージョンアップ
- v-data-tableバージョンアップ
- TypeError: Cannot create property ‘_destroyed’ on number ‘-1’
- 今回のコミット内容
Vuetifyバージョンアップ
% yarn add -D vuetify
package.json
- "vuetify": "^3.3.13"
+ "vuetify": "^3.4.3"
v-data-tableバージョンアップ
-
+
がVuetify Labs(Vuetify3)への変更箇所、
--
+-
++
がVuetify3への変更箇所です。
(Options API -> Composition API)components/members/Lists.vue
- <v-data-table
+ <v-data-table-server
v-if="members != null && members.length > 0"
v-model="syncSelectedMembers"
- :sort-by.sync="syncSort"
- :sort-desc.sync="syncDesc"
+ v-model:sort-by="syncSortBy"
:headers="headers"
:items="members"
+ :items-length="members.length"
- item-key="user.code"
:items-per-page="-1"
- hide-default-footer
- mobile-breakpoint="600"
++ density="compact"
++ hover
- :item-class="itemClass"
++ :row-props="rowProps"
fixed-header
-- :height="appTableHeight"
++ :height="tableHeight($vuetify.display.height)"
- must-sort
- :custom-sort="disableSortItem"
:show-select="admin"
+ :item-value="item => item"
-+ @dblclick:row="dblclickRow"
>
- </v-data-table>
+ </v-data-table-server>
-- <script>
++ <script setup lang="ts">
- export default {
+ export default defineNuxtComponent({
-- computed: {
-- syncSortBy: {
-- get () {
-- return [{ key: this.sort, order: this.desc ? 'desc' : 'asc' }]
-- },
-- set (value) {
-- if (value.length === 0) {
-- this.$emit('reload', { sort: this.sort, desc: !this.desc }) // NOTE: 同じ項目で並び順を2回変えると空になる為
-- } else {
-- this.$emit('reload', { sort: value[0].key, desc: value[0].order === 'desc' })
-- }
-- }
-- },
++ const syncSortBy: any = computed({
++ get: () => [{ key: $props.sort, order: $props.desc ? 'desc' : 'asc' }],
++ set: (value: any) => {
++ if (value.length === 0) {
++ $emit('reload', { sort: $props.sort, desc: !$props.desc }) // NOTE: 同じ項目で並び順を2回変えると空になる為
++ } else {
++ $emit('reload', { sort: value[0].key, desc: value[0].order === 'desc' })
++ }
++ }
++ })
-- methods: {
- disableSortItem (items) {
- return items
- },
- itemClass () {
- return (item) => {
- return this.activeUserCodes.includes(item.user?.code) ? 'row_active' : null
- }
- },
++ const rowProps = computed(() => ({ item }: any) => {
++ return $props.activeUserCodes.includes(item.user?.code) ? { class: 'row_active' } : null
++ })
densityのcompactとcomfortable/defaultは、ヘッダの高さの違い。
item-classはrow-propsに変更され、{ class: 'xxx' }
と指定するように変わっています。
mobile-breakpoint(モバイル表示)は無くなったので、必要なら自前で組む必要があります。
hover(マウスオーバーで色が変わる)がデフォルトfalseで追加されたので追加しました。
itemClassで指定したスタイルがあたらない
class名のtheme–dark/theme–lightの頭にv-
が追加された為。
<style scoped>
- .v-data-table.theme--dark >>> tr.row_active {
++ .v-data-table.v-theme--dark >>> tr.row_active {
background-color: #1A237E; /* indigo darken-4 */
}
- .v-data-table.theme--light >>> tr.row_active {
++ .v-data-table.v-theme--light >>> tr.row_active {
background-color: #E8EAF6; /* indigo lighten-5 */
}
- .v-data-table.theme--dark >>> tr:hover.row_active {
++ .v-data-table.v-theme--dark >>> tr:hover.row_active {
background-color: #283593 !important; /* indigo darken-3 */
}
- .v-data-table.theme--light >>> tr:hover.row_active {
++ .v-data-table.v-theme--light >>> tr:hover.row_active {
background-color: #C5CAE9 !important; /* indigo lighten-4 */
}
text/valueがtitle/keyに、class/cellClassがheaderProps/cellProps+class変わった
const headers: any = computed(() => {
const result = []
if ($props.admin) {
- result.push({ value: 'data-table-select', class: 'pl-3 pr-0', cellClass: 'pl-3 pr-0 py-2' })
++ result.push({ key: 'data-table-select', headerProps: { class: 'px-0' }, cellProps: { class: 'px-0 py-2' } })
}
- for (const item of this.$tm('items.member')) {
++ for (const item of Object.values($tm('items.member') as any) as any) {
- if ((item.required || !this.hiddenItems.includes(item.value)) && (!item.adminOnly || this.admin)) {
+ if ((item.required || !$props.hiddenItems.includes(item.key)) && (!item.adminOnly || $props.admin)) {
- result.push({ text: item.text, value: item.value, class: 'text-no-wrap', cellClass: 'px-1 py-2' })
++ result.push({ title: item.title, key: item.key, headerProps: { class: 'text-no-wrap' }, cellProps: { class: 'px-1 py-2' } })
}
}
- if (result.length > 0) { result[result.length - 1].cellClass = 'pl-1 pr-4 py-2' } // NOTE: スクロールバーに被らないようにする為
++ if (result.length > 0) { result[result.length - 1].cellProps.class = 'pl-1 pr-4 py-2' } // NOTE: スクロールバーに被らないようにする為
return result
})
itemがitem.rawに変わったが戻った
item: Vuetify2, Vuetify3
item.raw: Vuetify Labs
<template #[`item.user.name`]="{ item }">
<div class="ml-1">
-+ <UsersAvatar :user="item.user" />
+- <UsersAvatar :user="item.raw.user" />
methods: {
showUpdate (event, { item }) {
-+ if (!this.admin || item.user.code === this.$auth.user.code) { return }
+- if (!this.admin || item.raw.user.code === this.$auth.user.code) { return }
-+ this.$emit('showUpdate', item)
+- this.$emit('showUpdate', item.raw)
headerがcolumnに変わったが戻った。ソートアイコンが出なくなった
header: Vuetify2, Vuetify3
column: Vuetify Labs
- <template #[`header.user.email`]="{ header }">
+- <template #[`column.user.email`]="{ column, getSortIcon }">
++ <template #[`header.user.email`]="{ column, getSortIcon }">
- {{ header.text }}
+ {{ column.title }}
<OnlyIcon power="admin" />
+ <v-icon class="v-data-table-header__sort-icon">{{ getSortIcon(column) }}</v-icon>
</template>
slot内のaリンクに色や下線が付かなくなった
色や下線が付く: Vuetify2
色や下線が付かない: Vuetify Labs, Vuetify3
通常のaリンクに付く、これを追加しました。
a:-webkit-any-link {
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}
<template #[`item.power`]="{ item }">
<a
class="text-no-wrap"
+ style="color: -webkit-link; cursor: pointer; text-decoration: underline"
hide-default-footerが効かない
効く: Vuetify2
効かない: Vuetify Labs, Vuetify3
footerのSlotsがなさそうなので、CSSで対応しました。
<style scoped>
+ .v-data-table >>> .v-data-table-footer {
+- display: none; /* NOTE: hide-default-footerが効かない為 */
++ display: none; /* NOTE: フッタを非表示にする為 */
+ }
hide-default-headerが効かない
効く: Vuetify2
効かない: Vuetify Labs, Vuetify3
こちらはheadersのSlotsに空を渡せばOK。
components/spaces/Lists.vue
<v-data-table-server
>
+- <template #headers /><!-- NOTE: hide-default-headerが効かない為 -->
++ <template #headers /><!-- NOTE: ヘッダを非表示にする為 -->
disable-sortが効かない
効く: Vuetify2
効かない: Vuetify Labs, Vuetify3
すべて使わないは指定できなそうでしたが、
headersに「sortable: false」を追加すれば個別指定が可能。
components/invitations/Lists.vue
- result.push({ title: item.title, key: item.key })
+ result.push({ title: item.title, key: item.key, sortable: false })
‘item”は ‘unknown’ 型です。ts(18046)
まともに対応するの手間が大きそうなので、anyで逃げます。
- <template #[`item.user.name`]="{ item }">
+ <template #[`item.user.name`]="{ item }: any">
<div class="ml-1">
<UsersAvatar :user="item.user" />
TypeError: Cannot create property ‘_destroyed’ on number ‘-1’
Vuetifyをバージョンアップしたらエラーで落ちるようになりました。
% yarn test [Vue warn]: Unhandled error during execution of watcher callback atat TypeError: Cannot create property '_destroyed' on number '-1' ❯ clearImmediate node:timers:329:24 ❯ GlobalWindow.cancelAnimationFrame node_modules/happy-dom/src/window/Window.ts:921:10 ❯ node_modules/vuetify/lib/components/VSlideGroup/VSlideGroup.mjs:106:9 ❯ callWithErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:156:18 ❯ callWithAsyncErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:164:17 ❯ job node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:1812:9 ❯ flushPreFlushCbs node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:305:7 ❯ updateComponentPreRender node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5835:5 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5753:11 ❯ ReactiveEffect.run node_modules/@vue/reactivity/dist/reactivity.cjs.js:182:19
v-tab(v-tabsはOK)を消すとエラーがなくなり、落ちなくなる。バグかな?
testは非表示で暫定対応しちゃいます。
- <v-tabs v-model="tabPage" color="primary">
+ <v-tabs v-if="!$config.public.env.test" v-model="tabPage" color="primary">
$config.public.env.testは下記で取得しています。
nuxt.config.ts
const environment = process.env.NODE_ENV || 'development'
export default defineNuxtConfig({
runtimeConfig: {
public: Object.assign(commonConfig, config.envConfig, { env: { production: environment === 'production', test: false } })
test/setup.ts
config.global.mocks = {
$config: { public: Object.assign(helper.envConfig, helper.commonConfig, { env: { production: false, test: true } }) },
今回のコミット内容
origin#507 v-data-table恒久対応、vue-i18/Vuetifyバージョンアップ対応、AppMessage機能拡張、リファクタ