效果图
新建指令
Vue.directive('height', {
inserted(el, _binding, vnode) {
const paginationRef = vnode.context.$refs.paginationRef
const calculateHeight = () => {
const windowHeight = window.innerHeight
const topOffset = el.getBoundingClientRect().top
const otherElementsHeight = 40
let paginationHeight = 0
if (paginationRef && paginationRef.totalPage) {
paginationHeight = 55
}
el.style.height = `${
windowHeight - topOffset - otherElementsHeight - paginationHeight
}px`
}
const debouncedCalculateHeight = _.debounce(calculateHeight, 500)
debouncedCalculateHeight()
window.addEventListener('resize', debouncedCalculateHeight)
el.__vueHeightDirective__ = debouncedCalculateHeight
},
unbind(el) {
window.removeEventListener('resize', el.__vueHeightDirective__)
delete el.__vueHeightDirective__
}
})
页面使用
1:el-table外层嵌套div,加指令v-height
2:el-table设置height=100%
<div v-height>
<el-table height="100%">
</el-table-column>
</el-table>
</div>
注意,重点!
1:指令这一行 const paginationRef = vnode.context.$refs.paginationRef
用来判断是否显示分页器,所以如果有分页器需要在分页器增加ref,如下:
<el-pagination ref="paginationRef">
</el-pagination>
2:至于这一行 paginationRef.totalPage,是分页器的显示与否,比如:
<el-pagination v-if="total > 0" ref="paginationRef">
</el-pagination>
至于我这里为什么叫totalPage,因为这个是经过二次封装的,没封装的就直接叫total。
同理 指令paginationRef.totalPage需要修改为paginationRef.total
3:有人问了paginationRef.total这个total是怎么来的,怎么命名的;
这个是官网的文档的组件,paginationRef这里就会获取你分页器的props。
比如:
这个total就指的elementUI的分页组件的props。一般因为是用来判断total数量是不是大于0显示;
大于0就显示了分页器,所以。。。懂了吧
4:又有人问了,为什么指令不直接写在el-table里。这个你可以自己去试试,会发现滚动不了。
至于原因:因为这个指令设置的是单独style的height高度,你审查元素就会发现el-table传参的height 他需要同步设置为他下级元素样式el-table__body-wrapper的高度,所以并不是设置style为height的高度这么简单。
5:代码的_.debounce是什么。这里是用的lodash的防抖函数,自己写一个防抖函数即可。
6:有的同学就要问了,那我直接封装一个方法或者其他方法或者mixins来计算行不行
都可以,你想怎么用怎么用,mixins的话比如:
export default {
data() {
return {
tableHeight: 0
}
},
mounted() {
this.calculateAndSetHeight()
},
methods: {
calculateAndSetHeight() {
if (this.$refs.tableRef) {
const el = this.$refs.tableRef.$el
const calculateHeight = () => {
const windowHeight = window.innerHeight
const topOffset = el.getBoundingClientRect().top
const otherElementsHeight = 40
let paginationHeight = 0
const paginationRef = this.$refs.paginationRef
if (paginationRef && paginationRef.totalPage) {
paginationHeight = 55
}
this.tableHeight = `${
windowHeight - topOffset - otherElementsHeight - paginationHeight
}px`
}
const throttledCalculateHeight = _.debounce(calculateHeight, 500)
throttledCalculateHeight()
window.addEventListener('resize', throttledCalculateHeight)
// 在组件销毁时移除事件监听器
this.$once('hook:destroyed', () => {
window.removeEventListener('resize', throttledCalculateHeight)
})
}
}
}
}
页面使用:
<el-table ref="tableRef" :height="tableHeight">
这样就不用一个个标签像v-height div包起来了,但是ref和height就必要。
效果都是一样的,自己看着来。
ps:至于为什么要写这个功能,你能点进来看说明就是公司有一些犟货 觉得滚下去太麻烦了。或者是体验不是很好的,数据太多屏幕太小总要滚下去。
另外其实后台系统大部分用模板即可,有些模板自带有这种功能。
感谢你的阅读,如对你有帮助请收藏+关注!
只分享干货实战和精品,从不啰嗦!!!
如某处不对请留言评论,欢迎指正~
博主可收徒、常玩QQ飞车,可一起来玩玩鸭~