uni-app 微信小程序通过Vue3 Hooks 实现动态填充页面剩余高度

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

应用场景

在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绑定thisconst height = uni.getSystemInfoSync().windowHeight // 获取页面高度const topEl = uni.createSelectorQuery().in(currentInstance).select('#top')// 获取#top元素topEl.boundingClientRect((data) => {// 获取顶部高度topHeight.value = (data as any).heightscrollHeight.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> 
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})
}) 

CSS实现

感谢评论区大佬提醒🙏增加一种纯CSS实现scroll-view动态高度思路👇

  • 最外层page指定高度height:100%
  • 父元素设置display:flex,纵向布局flex-direction:columnheight:100vh溢出隐藏overflow:hidden
  • scorll-view设置flex:1 overflow:scroll,随便给个初始高度1px即可不影响布局效果
<template><view class="container"><view style="height: 100rpx; background-color: aquamarine;">我是标题</view><scroll-view scroll-y class="scroll-container"><view v-for="item in 100" :key="item">{{item}}</view></scroll-view><view style="height: 100rpx; background-color: aquamarine;">我是结尾</view></view>
</template> 
page{height:100%;// 重要
}
.container {display: flex;flex-direction:column;height:100vh;// 重要 设成100%小程序端会失效overflow:hidden;
}
.scroll-container {flex: 1;overflow: scroll;// 重要height: 0;
} 

微信小程序端效果展示

小程序端获取动态高度可能存在延迟本处使用watchEffect监听到变化后立即执行也可以考虑使用setTimeout进行延迟获取。

注意⚠️

1.获取节点高度首先要等节点渲染完成因此要在onReady中调用> 2.注意小程序端可能存在延迟考虑使用watchEffectsetTimeout延迟获取

最后

整理了75个JS高频面试题并给出了答案和解析基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴可以点击下方卡片领取无偿分享

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue