最近开发移动端h5,用的vant 移动端组件库框架,使用popup弹出层时,需要在底部固定一个操作模块。
但我发现在popup组件里使用fixed定位后,如果内容没有超出popup高度,底部fixed内容显示正常,否则内容超出出现滚动条后,底部fixed定位元素随页面滚动,fixed失效。效果如下:
正常情况和异常情况对比图(左正右异):
解决办法有两种方式
方式一:
<div class="box-man">
<van-popup
class="menu-pop"
v-model="showPopup"
closeable
close-on-popstate
position="right"
@close="close"
@open="open"
:lazy-render="false"
//overflow: 'hidden' 为了隐藏内容超出
:style="{ height: '100%', width: '100%', padding: '10% 6% 11%', overflow:
'hidden' }">
//渲染的数据
<div class="item" ref="itemBox">
<div v-for="(item, index) in topicList" :key="index">
<p v-text="item.title"></p>
</div>
</div>
//底部fixed元素
<div class="ft-btn" id="ft-btn">
<span v-text="`clear`"></span>
<van-button round block color="#391bf1" text="apply"></van-button>
</div>
</van-popup>
</div>
//所需样式
<style lang="stylus">
.box-man
//为了隐藏滚动条
.item
width: 110%
overflow: hidden
overflow-y: auto
.ft-btn
width: 100%
position: fixed;
left: 0
bottom: 0
border-top: 1px solid #e7e7e7
background-color: #fff;
</style>
//js代码
<script>
export default {
name: 'PopularTopicsPopup',
components: {},
props: {
showMenuPopup: {
type: Boolean,
default: false
}
},
data() {
return {
//控制popup的显示与隐藏
showPopup: this.showMenuPopup,
//模拟的数据
topicList: Array(30).fill({
title: 'Payments'
})
}
},
computed: {},
watch: {
showMenuPopup: {
handler(newval, oldval) {
this.showPopup = newval
},
immediate: true,
deep: true
}
},
created() {},
mounted() {},
// 销毁监听
destroyed() {},
methods: {
//关闭弹出层时触发
close() {
this.showPopup = false
this.$emit('showMenuPopups', this.showPopup)
},
//打开弹出层时触发
open() {
this.$nextTick(_ => {
this.getHight()
})
},
// 设置渲染数据内容区域的高度
getHight() {
//获取底部定位元素的高度和渲染数据盒子距离页面顶部距离
let h = document.getElementById('ft-btn').clientHeight,
itemOffTop = this.$refs.itemBox.offsetTop
//设置渲染数据盒子的高度 限制它只能在指定高度内滚动内容
this.$refs.itemBox.style.height =
document.documentElement.clientHeight - h - itemOffTop + 'px'
this.$forceUpdate()
}
}
}
</script>
效果图:
滑动到底部 能完全显示最后一项内容,并且底部fixed元素始终定位在底部。
方式二:
//html代码
<div class="box-man">
<van-popup
class="menu-pop"
v-model="showPopup"
closeable
close-on-popstate
position="right"
@close="close"
@open="open"
:lazy-render="false"
//overflow: 'hidden' 移除内容超出隐藏样式,把padding最后一个值改为0
:style="{ height: '100%', width: '100%', padding: '10% 6% 0' }">
//渲染的数据
<div class="item" ref="itemBox">
<div v-for="(item, index) in topicList" :key="index">
<p v-text="item.title"></p>
</div>
</div>
</van-popup>
//底部fixed元素
<div class="ft-btn" id="ft-btn" v-if="showPopup">
<span v-text="`clear`"></span>
<van-button round block color="#391bf1" text="apply"></van-button>
</div>
</div>
//所需样式
<style lang="stylus">
.box-man
//去除item样式
.item
/* width: 110%
overflow: hidden
overflow-y: auto */
.ft-btn
width: 100%
position: fixed;
left: 0
bottom: 0
border-top: 1px solid #e7e7e7
background-color: #fff;
</style>
//js代码
<script>
export default {
name: 'PopularTopicsPopup',
components: {},
props: {
showMenuPopup: {
type: Boolean,
default: false
}
},
data() {
return {
//控制popup的显示与隐藏
showPopup: this.showMenuPopup,
//模拟的数据
topicList: Array(30).fill({
title: 'Payments'
})
}
},
computed: {},
watch: {
showMenuPopup: {
handler(newval, oldval) {
this.showPopup = newval
},
immediate: true,
deep: true
}
},
created() {},
mounted() {},
// 销毁监听
destroyed() {},
methods: {
//关闭弹出层时触发
close() {
this.showPopup = false
this.$emit('showMenuPopups', this.showPopup)
},
//打开弹出层时触发
open() {
this.$nextTick(_ => {
this.getHight()
})
},
// 设置渲染数据内容区域的padding-bottom
getHight() {
//获取底部定位元素的高度
let h = document.getElementById('ft-btn').clientHeight
//设置渲染数据盒子的内下边距 为了解决元素被fixed定位元素遮挡问题
this.$refs.itemBox.style.paddingBottom = h + 'px'
this.$forceUpdate()
}
}
}
</script>
把需要定位的元素放在popup组件外,显示隐藏直接和控制弹出层的变量绑定同一个值,然后动态获取底部定位元素高度,赋值给渲染数据盒子的padding-bottom就可以了!
效果图:
滑动到底部 能完全显示最后一项内容,并且底部fixed元素始终定位在底部。