应用场景
在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:column
,height: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.注意小程序端可能存在延迟,考虑使用watchEffect
或setTimeout
延迟获取
最后
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
有需要的小伙伴,可以点击下方卡片领取,无偿分享