需求:制作网站时,顶部 header.vue(公共组件)需要随着网页内容垂直方向滚动时的位置变化,动态改变其背景色。

父组件 home.vue 代码:

<template>
    <Q-Header ref="myHeader"></Q-Header>
    <div ref="myDiv">
		父组件代码...
	</div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import QHeader from '@/components/header.vue'

const myHeader = ref<any>(null)
const myDiv = ref<any>(null)
const myDivH = ref<number>(0)
const oldScrollTop = ref<number>(0); // 记录上一次滚动结束后的滚动距离
const scrollTop = ref<number>(0); // 记录当前的滚动距离
const scrollHandle = () => {
    scrollTop.value = window.scrollY;	//滚动条距离浏览器顶部高度
    if (!myDivH.value) {
        myDivH.value = myDiv.value.offsetHeight;
    }
}
onMounted (() => {
    myHeader.value.setBgColor(0);   //将 header.vue组件的背景设置为透明
    window.addEventListener('scroll', scrollHandle);
})
onBeforeUnmount(() => {
    window.removeEventListener('scroll', scrollHandle)
})

watch(
    () => scrollTop.value,
    (newValue, oldValue) => {
         setTimeout(() => {
            if (newValue === window.scrollY) {
                // 延时执行后当newValue等于window.scrollY,代表滚动结束
                // console.log('滚动结束');
                oldScrollTop.value = newValue; // 每次滚动结束
                if (myDivH) {
                    let i = scrollTop.value / myDivH.value;
                    //调用子组件 header.vue 中的方法setBgColor,设置背景色
                    if (i > 1) {
                        myHeader.value.setBgColor(1)
                    } else {
                        myHeader.value.setBgColor(i.toFixed(2))
                    }
                }
            }
         }, 20); // 需要使用延时器,否则每次newValue和window.scrollY都相等,无法判断,20ms刚好大于watch的侦听周期,故延时20ms
        if (oldScrollTop.value === oldValue) {
            // 每次滚动开始时oldScrollTop与oldValue相等
            console.log('滚动开始');
        }
    }
)
</script>

子组件 header.vue 代码

<script setup lang="ts">
import { ref, defineExpose } from 'vue'

let bgColor = ref<string>(`rgb(37,41,46)`)

// 动态设置背景色透明度
const setBgColor = (v:number) => {
    bgColor.value = `rgba(37,41,46,${ v })`
}
defineExpose({ setBgColor })	//内部方法,供外部调用
</script>
<template>
    <div :style="{'background': bgColor}">
        <div>
            子组件代码...
        </div>
    </div>
</template>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐