theme: condensed-night-purple
应用场景
在uni-app开发微信小程序等项目时,经常会遇到这样的页面布局需求:上半部分高度固定,下半部分自动占满剩余高度,如下图所示应用场景:
上半部分为固定高度或内容填充高度
的内容区域
下半部分为scroll-view
滑动区域,可以无限下拉滚动进行数据加载
由于scroll-view
实现纵向滚动需要设置高度height
,如果设置一个固定的高度值将会使页面在不同屏幕尺寸下出现内容溢出屏幕或无法占满整个屏幕的情况,使页面看起来很不美观😅
因此为了提升用户体验,应该始终让整个页面保持在屏幕区域内固定,通过计算出页面的剩余高度,动态获取scroll-view
高度,从而实现滚动组件的高度自适应。
实现思路🤔?
页面剩余高度 = 屏幕高度 - 上方区域高度
由于微信小程序并非运行在浏览器环境下,因此如果进行直接进行DOM操作在H5端
运行正常,小程序端
会报错❌
还好uni-app官方提供了uni.createSelectorQuery()
和nodesRef.boundingClientRect(callback)
可以获取到小程序的节点和对应节点信息🎉
好的👌,那么大致的实现思路就已经确定了✅
- 通过
uni.getSystemInfoSync().windowHeight
获取到屏幕高度ScreenHeight🖥 - 给上方区域元素设置id=”top”
- 通过
uni.createSelectorQuery().in().select('#top')
获取上方区域节点 nodesRef.boundingClientRect(callback)
获取上方节点的高度信息TopHeight- ScrollHeight = ScreenHeight – TopHeight 计算出剩余高度,即滑动组件高度
封装Hooks📦
Vue3提供了Hooks
代替Vue2的mixins
进行复用逻辑抽离,考虑到大部分的滚动列表使用场景可能都需要动态计算高度,因此通过Hooks
进行代码抽离是很有必要的。
完整代码
// useScrollH.ts
/** Hooks 动态计算scrollList滑动区域高度
* @param {Number} offset 可选 -offset偏移量 手动微调scroll高度
* */
import { ref, getCurrentInstance } from 'vue'
export const useScrollHeight = (offset?: number):any => {
const scrollHeight = ref<number>(0) // scroll组件高度
const topHeight = ref<number>(0) // 组件上方占用高度
const currentInstance = getCurrentInstance(); // vue3绑定this
const height = uni.getSystemInfoSync().windowHeight // 获取页面高度
const topEl = uni.createSelectorQuery().in(currentInstance).select('#top') // 获取#top元素
topEl.boundingClientRect((data) => { // 获取顶部高度
topHeight.value = (data as any).height
scrollHeight.value = height - topHeight.value - (offset || 0) // 计算剩余高度 offset 偏移量
}).exec()
return scrollHeight
}
使用
<template>
<view>
<Tag id="top" />
<view>
...
<scroll-view :style="{'height': scrollH + 'px'}" scroll-y></scroll-view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, watchEffect } from 'vue';
import type { Ref } from 'vue';
import { useScrollHeight } from '@/config/utils/useScrollH';
import { onReady } from '@dcloudio/uni-app';
const scrollH = ref<number>(0) // scroll组件高度
...
// onReady中调用
onReady(() => {
let scrollHeight:Ref<number>;
scrollHeight = useScrollHeight()
watchEffect(() => {
scrollH.value = scrollHeight.value
})
})
</script>
小程序端获取动态高度可能存在延迟,本处使用
watchEffect
监听到变化后立即执行,也可以考虑使用setTimeout
进行延迟获取。
注意⚠️
1.获取节点高度首先要等节点渲染完成,因此要在
onReady
中调用
2.注意小程序端可能存在延迟,考虑使用watchEffect
或setTimeout
延迟获取
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容