Created
January 20, 2022 09:12
-
-
Save plusice/87e3e89cbba417dfff0c990723ed55b4 to your computer and use it in GitHub Desktop.
前端组件
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 使Ant Design Vue的Table组件支持表头sticky | |
* 单元格宽度必须固定 | |
*/ | |
import { throttle } from '../api/util'; | |
let listenAction; | |
let container; | |
let stickyHeader = null; | |
let originEl = null; | |
let bindingConfig = {}; | |
const originSelector = '.ant-table-content'; | |
const scrollSelector = '.ant-table-scroll .ant-table-body'; | |
const toRemoveSelector = '.ant-table-tbody,.ant-table-placeholder'; | |
const getBindingConfig = (binding) => { | |
const params = binding.value || {}; | |
const fixedTop = params.fixedTop || 0; | |
const zIndex = params.zIndex || 1000; | |
const bgColor = params.bgColor || '#fff'; | |
const { disabled } = params; | |
// 父元素的id | |
const { scrollContainerId } = params; | |
return { fixedTop, zIndex, disabled, scrollContainerId, bgColor }; | |
}; | |
const unwatch = () => { | |
container && container.removeEventListener('scroll', listenAction); | |
container && container.removeEventListener('resize', resizeStickyHeader); | |
originEl && originEl.querySelector(scrollSelector).removeEventListener('scroll', setScrollX); | |
}; | |
const watch = () => { | |
container && container.addEventListener('scroll', listenAction); | |
container && container.addEventListener('resize', resizeStickyHeader); | |
originEl && originEl.querySelector(scrollSelector).addEventListener('scroll', setScrollX); | |
}; | |
// 根据表格实际内容修改表头内容 | |
const adaptStickyHeader = () => { | |
stickyHeader.innerHTML = originEl.innerHTML; | |
stickyHeader.querySelector(scrollSelector).style.overflowX = 'hidden'; | |
const tbodyList = Array.from(stickyHeader.querySelectorAll(toRemoveSelector)); | |
tbodyList.forEach((tbody) => { | |
tbody.parentNode.removeChild(tbody); | |
}); | |
resizeStickyHeader(); | |
setScrollX(); | |
}; | |
// 根据实际内容设置宽度 | |
const resizeStickyHeader = throttle(() => { | |
stickyHeader.style.width = `${originEl.getBoundingClientRect().width}px`; | |
}); | |
// 根据表格横向滚动,设置sticky表头的横向位置 | |
const setScrollX = throttle(() => { | |
const stickyHeaderScroller = stickyHeader.querySelector(scrollSelector); | |
const originScroller = originEl.querySelector(scrollSelector); | |
stickyHeaderScroller.scrollLeft = originScroller.scrollLeft; | |
}); | |
export default { | |
bind(el, binding) { | |
originEl = el.querySelector(originSelector); | |
bindingConfig = getBindingConfig(binding); | |
const { disabled, fixedTop, zIndex, scrollContainerId, bgColor } = bindingConfig; | |
if (disabled) return; | |
container = document.getElementById(scrollContainerId) || window; | |
let active = false; | |
stickyHeader = originEl.cloneNode(true); | |
const stickyStyle = stickyHeader.style; | |
stickyStyle.cssText = `position: fixed;top: ${fixedTop}px; z-index: ${zIndex}; ${stickyStyle.cssText};background-color: ${bgColor}`; | |
const sticky = () => { | |
if (active) return; | |
setScrollX(); | |
originEl.insertAdjacentElement('afterend', stickyHeader); | |
active = true; | |
}; | |
const reset = () => { | |
if (!active) return; | |
stickyHeader.parentNode?.removeChild(stickyHeader); | |
active = false; | |
}; | |
listenAction = throttle(() => { | |
const rectEl = originEl?.parentNode; | |
const rect = rectEl.getBoundingClientRect(); | |
const offsetTop = rect.top; | |
if (offsetTop <= fixedTop) { | |
return sticky(); | |
} | |
reset(); | |
}); | |
watch(); | |
}, | |
unbind: unwatch, | |
update(el, binding) { | |
bindingConfig = getBindingConfig(binding); | |
originEl = el.querySelector(originSelector); | |
if (bindingConfig.disabled) { | |
stickyHeader.parentNode?.removeChild(stickyHeader); | |
unwatch(); | |
return; | |
} | |
adaptStickyHeader(); | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment