@ -1,17 +1,19 @@
@@ -1,17 +1,19 @@
< template >
< div class = "list-table-v2" :style ="containerStyle" >
<!-- Probe row for measuring actual row height ( only when using dynamic height mode ) -- >
< div v-if ="shouldUseProbeRow" ref="probeRowRef" class="probe-row" aria-hidden="true" >
< div v-if ="probeRowData" class="probe-cell" >
< template v-for ="item in prop.columns || []" :key="item.key" >
< span class = "probe-content" >
{ { getProbeCellText ( probeRowData , item ) } }
< / span >
< / template >
<!-- Mini hidden table for measuring row height ( only when using dynamic height mode ) -- >
< div v-if ="shouldUseProbeRow" ref="miniTableRef" class="mini-table" aria-hidden="true" >
< div v-if ="miniTableData.length > 0" class="mini-table-inner" >
< div v-for ="(row, idx) in miniTableData" :key="idx" class="mini-row" >
< div v-for ="item in prop.columns || []" :key="item.key" class="mini-cell" >
< span class = "mini-cell-content" >
{ { getProbeCellText ( row , item ) } }
< / span >
< / div >
< / div >
< / div >
< / div >
< div class = "my-table" >
< div ref = "myTableRef" class = "my-table" >
< el -auto -resizer >
< template # default = "{ height, width }" >
< el -table -v2
@ -61,13 +63,11 @@ const slots = useSlots();
@@ -61,13 +63,11 @@ const slots = useSlots();
const { t } = useI18n ( ) ;
const { state } = useStore ( ) ;
const table = ref ( ) ;
const probeRowRef = ref ( ) ;
const probeRowData = ref ( ) ;
const miniTableRef = ref ( ) ;
const myTableRef = ref ( ) ; / / R e f e r e n c e t o . m y - t a b l e f o r R e s i z e O b s e r v e r
const miniTableData = ref < any [ ] > ( [ ] ) ;
const estimatedRowHeight = ref < number | undefined > ( undefined ) ;
/ / D e b o u n c e d r e s i z e h a n d l e r f o r r e - m e a s u r i n g p r o b e r o w
/ / U s e L o d a s h D e b o u n c e f o r p r o p e r c a n c e l ( ) m e t h o d t y p i n g
const debouncedResizeHandler = ref < lodash .DebouncedFunc < ( ) = > void > | undefined > ( undefined ) ;
let miniTableResizeObserver : ResizeObserver | null = null ;
/ / H e a d e r h e i g h t c o n s t a n t
@ -194,22 +194,25 @@ const estimatedRowHeightToUse = computed(() => {
@@ -194,22 +194,25 @@ const estimatedRowHeightToUse = computed(() => {
return estimatedRowHeight . value ; / / u s e p r o b e - m e a s u r e d v a l u e
} ) ;
/ / M e a s u r e p r o b e r o w h e i g h t w h e n d a t a c h a n g e s ( o n l y w h e n u s i n g p r o b e r o w )
/ / M e a s u r e m i n i t a b l e r o w h e i g h t w h e n d a t a c h a n g e s ( o n l y w h e n u s i n g p r o b e r o w )
/ / W e u s e T W O f r a m e s d e l a y t o l e t e l - t a b l e - v 2 f u l l y s e t t l e b e f o r e m e a s u r i n g
watch (
( ) => pageData . value ? . [ 0 ] ,
async ( firstRow ) => {
/ / S k i p i f r o w H e i g h t i s s e t ( f i x e d h e i g h t m o d e ) o r a l r e a d y h a v e a v a l u e
if ( ! shouldUseProbeRow . value || ! firstRow ) {
( ) => pageData . value ,
async ( data ) => {
/ / S k i p i f r o w H e i g h t i s s e t ( f i x e d h e i g h t m o d e ) o r n o d a t a
if ( ! shouldUseProbeRow . value || ! data || data . length === 0 ) {
return ;
}
probeRowData . value = firstRow ;
/ / W a i t f o r p r o b e t o r e n d e r
/ / U s e u p t o 5 r o w s f o r m i n i t a b l e
miniTableData . value = data . slice ( 0 , 5 ) ;
/ / W a i t f o r m i n i t a b l e t o r e n d e r
await nextTick ( ) ;
/ / W a i t T W O f r a m e s f o r e l - t a b l e - v 2 t o f u l l y s e t t l e i t s l a y o u t
/ / W a i t T W O f r a m e s f o r l a y o u t t o s e t t l e
await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) ) ;
await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) ) ;
const height = probeRowRef . value ? . offsetHeight ;
/ / M e a s u r e f i r s t r o w h e i g h t
const firstRow = miniTableRef . value ? . querySelector ( ".mini-row" ) ;
const height = firstRow ? . offsetHeight ;
if ( height && height > 0 ) {
estimatedRowHeight . value = height ;
}
@ -217,45 +220,46 @@ watch(
@@ -217,45 +220,46 @@ watch(
{ immediate : true }
) ;
/ / S e t u p r e s i z e l i s t e n e r o n m o u n t
/ / S e t u p R e s i z e O b s e r v e r o n m o u n t ( n o t w i n d o w r e s i z e - t h a t c a u s e s f l i c k e r i n g )
onMounted ( ( ) => {
/ / C r e a t e d e b o u n c e d h a n d l e r
debouncedResizeHandler . value = lodash . debounce ( ( ) => {
/ / O n l y r e - m e a s u r e i n d y n a m i c h e i g h t m o d e
if ( shouldUseProbeRow . value ) {
measureProbeRow ( ) ;
/ / C r e a t e d e b o u n c e d r e s i z e h a n d l e r f o r m i n i t a b l e w i d t h c h a n g e s
const debouncedMeasure = lodash . debounce ( async ( ) => {
if ( ! shouldUseProbeRow . value || miniTableData . value . length === 0 ) {
return ;
}
} , 250 ) ; / / 2 5 0 m s d e b o u n c e d e l a y
/ / C l e a r p r e v i o u s m e a s u r e m e n t s o e l - t a b l e - v 2 r e c a l c u l a t e s
estimatedRowHeight . value = undefined ;
await nextTick ( ) ;
/ / W a i t T W O f r a m e s f o r l a y o u t t o s e t t l e
await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) ) ;
await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) ) ;
/ / M e a s u r e f i r s t r o w h e i g h t
const firstRow = miniTableRef . value ? . querySelector ( ".mini-row" ) ;
const height = firstRow ? . offsetHeight ;
if ( height && height > 0 ) {
estimatedRowHeight . value = height ;
}
} , 100 ) ;
/ / U s e R e s i z e O b s e r v e r o n . m y - t a b l e t o d e t e c t w i d t h c h a n g e s
/ / T h i s i s b e t t e r t h a n w i n d o w r e s i z e b e c a u s e i t o n l y f i r e s w h e n O U R c o n t a i n e r c h a n g e s
miniTableResizeObserver = new ResizeObserver ( ( ) => {
debouncedMeasure ( ) ;
} ) ;
/ / A t t a c h w i n d o w r e s i z e l i s t e n e r
window . addEventListener ( "resize" , debouncedResizeHandler . value ) ;
if ( myTableRef . value ) {
miniTableResizeObserver . observe ( myTableRef . value ) ;
}
} ) ;
/ / C l e a n u p o n u n m o u n t
onUnmounted ( ( ) => {
if ( debouncedResizeHandler . value ) {
window . removeEventListener ( "resize" , debouncedResizeHandler . value ) ;
debouncedResizeHandler . value . cancel ( ) ; / / C a n c e l a n y p e n d i n g d e b o u n c e c a l l s
if ( miniTableResizeObserver ) {
miniTableResizeObserver . disconnect ( ) ;
miniTableResizeObserver = null ;
}
} ) ;
/ / F u n c t i o n t o r e - m e a s u r e p r o b e r o w h e i g h t ( f o r r e s i z e h a n d l i n g )
const measureProbeRow = async ( ) => {
if ( ! shouldUseProbeRow . value || ! probeRowData . value ) {
return ;
}
/ / C l e a r p r e v i o u s m e a s u r e m e n t s o e l - t a b l e - v 2 r e c a l c u l a t e s
estimatedRowHeight . value = undefined ;
await nextTick ( ) ;
/ / W a i t T W O f r a m e s f o r e l - t a b l e - v 2 t o f u l l y s e t t l e i t s l a y o u t
await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) ) ;
await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) ) ;
const height = probeRowRef . value ? . offsetHeight ;
if ( height && height > 0 ) {
estimatedRowHeight . value = height ;
}
} ;
const containerStyle = computed ( ( ) => {
const style : Record < string , string > = { } ;
if ( prop . height !== undefined ) {
@ -455,26 +459,55 @@ const tableColumns = computed(() => {
@@ -455,26 +459,55 @@ const tableColumns = computed(() => {
position : relative ;
}
/ / P r o b e r o w f o r m e a s u r i n g a c t u a l r o w h e i g h t
. probe - row {
/ / M i n i h i d d e n t a b l e f o r m e a s u r i n g r o w h e i g h t ( f l e x b o x e s , n o t e l - t a b l e - v 2 )
. mini - table {
position : absolute ;
visibility : hidden ;
pointer - events : none ;
left : - 9999 px ;
top : 0 ;
width : 100 % ; / / W i d t h r e s p o n d s t o p a r e n t c o n t a i n e r
max - width : 100 % ;
}
. probe - cell {
. mini - table - inner {
display : flex ;
flex - direction : column ;
width : 100 % ;
}
. mini - row {
display : flex ;
align - items : center ;
padding : v - bind ( "state.size.tablePad" ) ;
border - right : var ( -- el - table - border ) ;
border - bottom : var ( -- el - table - border ) ;
background : v - bind ( "state.style.tableBg" ) ;
color : v - bind ( "state.style.tableColor" ) ;
box - sizing : border - box ;
}
. mini - cell {
flex : 1 ;
min - width : 120 px ;
padding - right : 8 px ;
box - sizing : border - box ;
overflow : hidden ;
text - overflow : ellipsis ;
white - space : nowrap ;
}
. probe - content {
/ / F l e x g r o w c o l u m n s m a t c h t h e r e a l t a b l e ' s f l e x d i s t r i b u t i o n
. mini - cell : nth - child ( 1 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 2 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 3 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 4 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 5 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 6 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 7 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell : nth - child ( 8 ) { flex : 1 ; min - width : 120 px ; }
. mini - cell - content {
overflow : hidden ;
text - overflow : ellipsis ;
}
@ -486,6 +519,7 @@ const tableColumns = computed(() => {
@@ -486,6 +519,7 @@ const tableColumns = computed(() => {
display : flex ;
flex - direction : column ;
overflow : hidden ;
position : relative ; / / F o r m i n i - t a b l e ' s c o n t a i n i n g b l o c k
}
. my - table : deep ( . el - table - v2 ) {