Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
3a113481
Commit
3a113481
authored
Apr 13, 2026
by
qingyuzhang
Browse files
fix(frontend): avoid mounting hidden mobile table
parent
ad64190b
Changes
1
Show whitespace changes
Inline
Side-by-side
frontend/src/components/common/DataTable.vue
View file @
3a113481
<
template
>
<div
class=
"md:hidden
space-y-3"
>
<div
v-if=
"!isDesktopViewport"
class=
"
space-y-3"
>
<template
v-if=
"loading"
>
<div
v-for=
"i in 5"
:key=
"i"
class=
"rounded-lg border border-gray-200 bg-white p-4 dark:border-dark-700 dark:bg-dark-900"
>
<div
class=
"space-y-3"
>
...
...
@@ -61,8 +61,9 @@
</div>
<div
v-else
ref=
"tableWrapperRef"
class=
"table-wrapper
hidden md:block
"
class=
"table-wrapper"
:class=
"{
'actions-expanded': actionsExpanded,
'is-scrollable': isScrollable
...
...
@@ -203,6 +204,11 @@ import Icon from '@/components/icons/Icon.vue'
const
{
t
}
=
useI18n
()
const
desktopViewportQuery
=
'
(min-width: 768px)
'
const
isDesktopViewport
=
ref
(
typeof
window
===
'
undefined
'
?
true
:
window
.
matchMedia
(
desktopViewportQuery
).
matches
)
const
emit
=
defineEmits
<
{
sort
:
[
key
:
string
,
order
:
'
asc
'
|
'
desc
'
]
}
>
()
...
...
@@ -268,8 +274,19 @@ const checkActionsColumnWidth = () => {
// 监听尺寸变化
let
resizeObserver
:
ResizeObserver
|
null
=
null
let
resizeHandler
:
(()
=>
void
)
|
null
=
null
let
desktopViewportMediaQuery
:
MediaQueryList
|
null
=
null
let
desktopViewportListener
:
((
event
:
MediaQueryListEvent
)
=>
void
)
|
null
=
null
onMounted
(()
=>
{
const
detachDesktopTableTracking
=
()
=>
{
resizeObserver
?.
disconnect
()
resizeObserver
=
null
if
(
resizeHandler
)
{
window
.
removeEventListener
(
'
resize
'
,
resizeHandler
)
resizeHandler
=
null
}
}
const
attachDesktopTableTracking
=
()
=>
{
checkScrollable
()
checkActionsColumnWidth
()
if
(
tableWrapperRef
.
value
&&
typeof
ResizeObserver
!==
'
undefined
'
)
{
...
...
@@ -286,14 +303,34 @@ onMounted(() => {
}
window
.
addEventListener
(
'
resize
'
,
resizeHandler
)
}
}
onMounted
(()
=>
{
if
(
typeof
window
!==
'
undefined
'
)
{
desktopViewportMediaQuery
=
window
.
matchMedia
(
desktopViewportQuery
)
isDesktopViewport
.
value
=
desktopViewportMediaQuery
.
matches
desktopViewportListener
=
(
event
:
MediaQueryListEvent
)
=>
{
isDesktopViewport
.
value
=
event
.
matches
}
if
(
typeof
desktopViewportMediaQuery
.
addEventListener
===
'
function
'
)
{
desktopViewportMediaQuery
.
addEventListener
(
'
change
'
,
desktopViewportListener
)
}
else
{
desktopViewportMediaQuery
.
addListener
(
desktopViewportListener
)
}
}
})
onUnmounted
(()
=>
{
resizeObserver
?.
disconnect
()
if
(
resizeHandler
)
{
window
.
removeEventListener
(
'
resize
'
,
resizeHandler
)
resizeHandler
=
null
detachDesktopTableTracking
()
if
(
desktopViewportMediaQuery
&&
desktopViewportListener
)
{
if
(
typeof
desktopViewportMediaQuery
.
removeEventListener
===
'
function
'
)
{
desktopViewportMediaQuery
.
removeEventListener
(
'
change
'
,
desktopViewportListener
)
}
else
{
desktopViewportMediaQuery
.
removeListener
(
desktopViewportListener
)
}
desktopViewportListener
=
null
}
desktopViewportMediaQuery
=
null
})
interface
Props
{
...
...
@@ -470,6 +507,17 @@ const columnsSignature = computed(() =>
props
.
columns
.
map
((
column
)
=>
`
${
column
.
key
}
:
${
column
.
sortable
?
'
1
'
:
'
0
'
}
`
).
join
(
'
|
'
)
)
watch
(
isDesktopViewport
,
async
(
isDesktop
)
=>
{
detachDesktopTableTracking
()
if
(
!
isDesktop
)
return
await
nextTick
()
attachDesktopTableTracking
()
},
{
immediate
:
true
,
flush
:
'
post
'
}
)
// 数据/列变化时重新检查滚动状态
// 注意:不能监听 actionsExpanded,因为 checkActionsColumnWidth 会临时修改它,会导致无限循环
watch
(
...
...
@@ -526,7 +574,7 @@ const sortedData = computed(() => {
// --- Virtual scrolling ---
const
rowVirtualizer
=
useVirtualizer
(
computed
(()
=>
({
count
:
sortedData
.
value
?.
length
??
0
,
count
:
isDesktopViewport
.
value
?
(
sortedData
.
value
?.
length
??
0
)
:
0
,
getScrollElement
:
()
=>
tableWrapperRef
.
value
,
estimateSize
:
()
=>
props
.
estimateRowHeight
??
56
,
overscan
:
props
.
overscan
??
5
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment