|
|
<template> <view class=""> <view class="u-sticky-wrap" :class="[elClass]" :style="{ height: fixed ? height + 'px' : 'auto', backgroundColor: bgColor }"> <view class="u-sticky" :style="{ position: fixed ? 'fixed' : 'static', top: stickyTop + 'px', left: left + 'px', width: width == 'auto' ? 'auto' : width + 'px', zIndex: uZIndex }"> <slot></slot> </view> </view> </view> </template>
<script> /** * sticky 吸顶 * @description 该组件与CSS中position: sticky属性实现的效果一致,当组件达到预设的到顶部距离时, 就会固定在指定位置,组件位置大于预设的顶部距离时,会重新按照正常的布局排列。 * @tutorial https://www.uviewui.com/components/sticky.html
* @property {String Number} offset-top 吸顶时与顶部的距离,单位rpx(默认0) * @property {String Number} index 自定义标识,用于区分是哪一个组件 * @property {Boolean} enable 是否开启吸顶功能(默认true) * @property {String} bg-color 组件背景颜色(默认#ffffff) * @property {String Number} z-index 吸顶时的z-index值(默认970) * @property {String Number} h5-nav-height 导航栏高度,自定义导航栏时(无导航栏时需设置为0),需要传入此值,单位px(默认44) * @event {Function} fixed 组件吸顶时触发 * @event {Function} unfixed 组件取消吸顶时触发 * @example <u-sticky offset-top="200"><view>塞下秋来风景异,衡阳雁去无留意</view></u-sticky> */ export default { name: "u-sticky", props: { // 吸顶容器到顶部某个距离的时候,进行吸顶,在H5平台,NavigationBar为44px
offsetTop: { type: [Number, String], default: 0 }, //列表中的索引值
index: { type: [Number, String], default: '' }, // 是否开启吸顶功能
enable: { type: Boolean, default: true }, // h5顶部导航栏的高度
h5NavHeight: { type: [Number, String], default: 44 }, // 吸顶区域的背景颜色
bgColor: { type: String, default: '#ffffff' }, // z-index值
zIndex: { type: [Number, String], default: '' } }, data() { return { fixed: false, height: 'auto', stickyTop: 0, elClass: this.$u.guid(), left: 0, width: 'auto', }; }, watch: { offsetTop(val) { this.initObserver(); }, enable(val) { if (val == false) { this.fixed = false; this.disconnectObserver('contentObserver'); } else { this.initObserver(); } } }, computed: { uZIndex() { return this.zIndex ? this.zIndex : this.$u.zIndex.sticky; } }, mounted() { this.initObserver(); }, methods: { initObserver() { if (!this.enable) return; // #ifdef H5
this.stickyTop = this.offsetTop != 0 ? uni.upx2px(this.offsetTop) + this.h5NavHeight : this.h5NavHeight; // #endif
// #ifndef H5
this.stickyTop = this.offsetTop != 0 ? uni.upx2px(this.offsetTop) : 0; // #endif
this.disconnectObserver('contentObserver'); this.$uGetRect('.' + this.elClass).then((res) => { this.height = res.height; this.left = res.left; this.width = res.width; this.$nextTick(() => { this.observeContent(); }); }); }, observeContent() { this.disconnectObserver('contentObserver'); const contentObserver = this.createIntersectionObserver({ thresholds: [0.95, 0.98, 1] }); contentObserver.relativeToViewport({ top: -this.stickyTop }); contentObserver.observe('.' + this.elClass, res => { if (!this.enable) return; this.setFixed(res.boundingClientRect.top); }); this.contentObserver = contentObserver; }, setFixed(top) { const fixed = top < this.stickyTop; if (fixed) this.$emit('fixed', this.index); else if(this.fixed) this.$emit('unfixed', this.index); this.fixed = fixed; }, disconnectObserver(observerName) { const observer = this[observerName]; observer && observer.disconnect(); }, }, beforeDestroy() { this.disconnectObserver('contentObserver'); } }; </script>
<style scoped lang="scss"> @import "../../libs/css/style.components.scss"; .u-sticky { z-index: 9999999999; } </style>
|