vue3手搓固钉组件

#创作灵感

        今天用固钉组件时发现element-ui的固钉会阻止移动端移动事件,我思来想去决定自己写一个固定组件得了


实现思路

        获取钉子的ref实例并监听window滚动事件,当window.scrollY等于钉子的offsetHeight,添加position:fixed和top:0到钉子上,就能强行固定不动了。

        这时候会有一个bug:如果元素本来并没有定位,直接添加定位属性会使其脱离文档流造成周围元素坍塌,这该怎么办?于是我再在下面添加一个div作为占位符,当内容被固定上去时,v-if渲染一个相同高度的div撑着文档流的内容,防止坍塌。slot插槽可以自由添加内容。最好在使用时加入z-index保证固钉优先显示

        不知道为什么固定上去还需要额外设置宽度和原来一样,这点我也不懂

        如果不生效,可以把affixStyle提出来放到一个类里,通过条件判断是否增加类来实现属性的改变

<template>
<!-- 我是钉子 -->
<div ref="dingzi" :style="affixStyle">
    <slot></slot>
</div>
<!-- 我是占位符 -->
<div v-if="isTop" :style="{height:theHeight + 'px'}" >
</div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const dingzi = ref(null)
const affixStyle = ref({}) // 固钉样式
const offsetT = ref()
const isTop = ref(false)
const theHeight = ref(0)
const handleScroll = () =>{
    if (offsetT.value - window.scrollY <= 0 ){
        affixStyle.value = {
            position: 'fixed',
            top: '0rem',
            width:`${dingzi.value.offsetWidth}px` // 需要保持宽度不变 不然不知道为什么会坍塌
        }
        console.log('我在滚');

        isTop.value = true
        theHeight.value = dingzi.value.offsetHeight;
    }else{
        affixStyle.value = {}
        isTop.value = false
    }
}
onMounted(()=>{
    window.addEventListener('scroll', handleScroll)
    offsetT.value = dingzi.value.offsetTop
})
onUnmounted(()=>{
    window.removeEventListener('scroll', handleScroll)
})
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值