今天,做pc后台新系统进行layout布局的时候,有一个需求,页面布局如图
其实这种常规布局,侧边栏固定菜单,我们直接fixed定位,右边栏直接使用margin-left就好了,主要的问题是要如何实时计算content内容块的高度,在header内容随时会改变的情况下。
其实,我的想法是实时获取content的距离可视化区域的top值,然后通过100vh - top值 - footer固定高度来算出这块内容的高度。
所以问题来了,如何实时获取这个top值呢?这里碰了几个坑,分享下,我尝试使用watchEffect、vueuse插件里的useIntersectionObserver实时获取elementRef的top值的更新,但发现不管怎么操作,elementRef都只更新一次,当变化的时候根本监听不到,这是为啥呢?真的一脸懵逼。懂得帮忙解答下哈。
于是,我转了另一种想法,既然更新时监听,onUpdated岂不是很香,哇塞,终于找到了这个生命周期的应用场景了,于是,我直接封装了一个useElementOffset的hook方法,直接看代码:
import { ref, onMounted, onUpdated, nextTick } from 'vue'
/**
* @params elementRef 对应的绑定vnode
* /
export const useElementOffset = (elementRef) => {
const offsetTop = ref(0)
// 获取elementRef的top值
const updateOffsetTop = () => {
const element = elementRef.value
if (element && element?.$el) {
const top = elementRef.value.$el?.getBoundingClientRect?.()?.top
offsetTop.value = top ?? element.$el?.offsetTop
}
}
onMounted(() => {
// 首次渲染期间更新一次
updateOffsetTop()
})
onUpdated(async () => {
// 防止获取不到top或者值不准确
await nextTick()
// 每次更新,就重新获取它的top值
updateOffsetTop()
})
return { offsetTop }
}
其实这个还是有点bug,如页面resize时,根本没实时获取,所以要再监听resize变化时会更好。但因为只是后台系统,所以就没去较真这一个。
该方法使用方式如下(以jsx写法为例):
setup() {
const myRef = ref();
const { offsetTop } = useElementOffset(myRef);
return (<div ref={myRef} style={{height: `calc(100vh - ${offsetTop}px)`}}></div>)
}