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バージョンアップ

% 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 
  at  
  at  

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機能拡張、リファクタ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です