Vue3中到达可视区域后执行

项目场景:

提示:这里简述项目相关背景:

在项目中有时候需要显示一些动态效果,但是如果页面过长刷新页面的时候有些效果在没看到的时候就会执行,那么能滚动到那个区域的时候哪些动态效果就在没看到的时候就已经执行过了,那怎么才能让后滚动到可视区域的时候才执行呢?

在Vue 3中,要判断一个元素是否到达可视区域,你可以使用几种不同的方法。最常见和直接的方法是利用Intersection Observer API

Intersection Observer是一个非常强大的API,可以自动"观察"目标元素是否进入其祖先元素或顶级文档视口的可见区域。

到达可视区域的时候就会执行


分析:

提示:这里填写问题的分析:

首先需要时vue3项目,另外,要在onMounted钩子函数中作操作

基本操作如下

1:使用Intersection Observer

html 复制代码
<template>
  <div ref="observerElement" class="observed-element">
    我是需要观察的元素
  </div>
</template>
 
<script setup>
import { ref, onMounted } from 'vue';
 
const observerElement = ref(null);
 
onMounted(() => {
  const options = {
    root: null, // 使用视口作为参照点
    rootMargin: '0px',
    threshold: 0.1 // 元素10%在视口内时触发回调
  };
 
  const callback = (entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        console.log('元素进入了视口!');
      } else {
        console.log('元素离开了视口。');
      }
    });
  };
 
  const observer = new IntersectionObserver(callback, options);
  if (observerElement.value) {
    observer.observe(observerElement.value);
  }
});
</script>

2:计算元素位置与视口的关系

如果你不希望使用Intersection Observer API,你可以通过计算元素的位置来判断它是否进入视口。这通常涉及到获取元素的位置和视口的高度。

html 复制代码
<template>
  <div ref="element" class="observed-element">我是需要观察的元素</div>
</template>
 
<script setup>
import { ref, onMounted } from 'vue';
 
const element = ref(null);
 
onMounted(() => {
  const checkVisibility = () => {
    if (!element.value) return;
    const rect = element.value.getBoundingClientRect();
    const isVisible = (
      rect.top >= 0 &&
      rect.left >= 0 &&
      rect.bottom 
      <= 
      (window.innerHeight || document.documentElement.clientHeight) &&
      rect.right 
      <= 
      (window.innerWidth || document.documentElement.clientWidth)
    );
    if (isVisible) {
      console.log('元素进入了视口!');
    } else {
      console.log('元素离开了视口。');
    }
  };
  checkVisibility(); // 初始检查一次
  // 添加滚动事件监听器以持续检查
  window.addEventListener('scroll', checkVisibility); 
  // 添加窗口大小改变事件监听器以持续检查
  window.addEventListener('resize', checkVisibility); 
});
</script>

方案实例:

提示:这里填写该问题的具体解决方案:

在组件中使用这个方法直接在子组件中使用不需要再父组件中操作

如下:

父组件:

javascript 复制代码
<!-- 使用子组件 -->
    <bannerGreen
    :bannerInfo="bannerInfo"/>

//引入子组件
import bannerGreen from '@/view/Home/components/bannerGreen.vue';
    

子组件

javascript 复制代码
<template>
  <div 
    ref="observerElement" 
    class="observed-element flexEv bannerBg padTB100 padLR65 colorW">
    <div class="flex" v-for="item in props.bannerInfo">
      <div class="borderR paddingR20 flexC">
        <i 
           :class="item.icon" 
           class="iconfont fontS40 fontW4 colorW hoverS"></i>
      </div>
      <div class="paddingL20">
        <div 
          ref="numRef" 
          class="fontS26 fontW6 marginB10 number inLb"
          :data-target="item.textTop"></div> 
        <div class="fontS26 fontW6 inLb">+</div>
        <div class="fontS18 fontW5">{{item.textBottom}}</div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {
  reactive,
  toRefs,
  ref,
  Ref,
  PropType,
  onMounted,
  onBeforeUnmount,
} from "vue"
const props=defineProps({
  // 
  bannerInfo:{
    type:Array
  },
})
// 自动将数值加到会后那个值的方法
const changeNum=()=>{
  // 获取元素
  const numbers = document.querySelectorAll('.number')
  console.log("",numbers)
  // 获取所有的dom,querySelectorAll为为数组
  numbers.forEach(item => {
    item.textContent = "0";
    const upDateNumber = () => {
      // 获取每个类名为number的data-target,即获取最大值 
      const target = Number(item.getAttribute('data-target'))
      // 获取当前div的数值
      const d = Number(item.textContent)
      // 设置数据增加的值,可以通过target除的数值确定怎么加数值的快慢
      const increment = target / 100
      // 当数字小于最大值时,执行下面的操作
      if (d < target) {
        // 向上取整
        item.textContent = `${Math.ceil(d + increment)}`
        // 1ms重新调用,不然它会在第一次运行完就结束
        setTimeout(upDateNumber, 10)
      } else {
        item.textContent = target+"";//textContent的值是 字符串 所以加个空字符
      }
    }
    upDateNumber()
  })
}
onMounted(()=>{
  console.log()
  
})
// ================================到达可视区域的方法
const observerElement = ref(null);
onMounted(() => {
  const options = {
    root: null, // 使用视口作为参照点
    rootMargin: '0px',
    threshold: 0.1 // 元素10%在视口内时触发回调
  };
  const callback = (entries:any, observer:any) => {
    entries.forEach((entry:any) => {
      if (entry.isIntersecting) {
        console.log('元素进入了视口!');
        //到达可视区域 执行 数字自增的方法
        changeNum()
      } else {
        console.log('元素离开了视口。');
      }
    });
  };
  const observer = new IntersectionObserver(callback, options);
  if (observerElement.value) {
    observer.observe(observerElement.value);
  }
});
onBeforeUnmount(()=>{
  console.log()
})
const emit =defineEmits([
  ""
])

</script>

<style lang="less" scoped>
.bannerBg{
  background-color:#1d7b51 ;
}
.borderR{
  border-right: 1px solid #ffffff;
}
</style>
相关推荐
BillKu4 分钟前
Vue3取消网络请求的方法(AbortController)
前端·javascript·vue.js
海天胜景33 分钟前
c# list<T> 合并
前端·c#
陈奕昆2 小时前
【LLaMA-Factory实战】Web UI快速上手:可视化大模型微调全流程
前端·ui·llama·大模型微调实战
Jedi Hongbin2 小时前
echarts自定义图表--柱状图-横向
前端·javascript·echarts
3D虚拟工厂3 小时前
1️⃣7️⃣three.js_OrbitControls相机控制器
javascript·3d·vue·blender·three.js·uv
Yan-英杰3 小时前
npm error code CERT_HAS_EXPIRED
服务器·前端·数据库·人工智能·mysql·npm·node.js
武昌库里写JAVA3 小时前
iView Admin的side menu改为top menu
java·vue.js·spring boot·课程设计·宠物管理
sunly_4 小时前
Flutter:组件10、倒计时
开发语言·javascript·flutter
BillKu4 小时前
前端Vue3 + 后端Spring Boot,前端取消请求后端处理逻辑分析
java·vue.js·spring boot
徐白11774 小时前
Node.js 事件循环和线程池任务完整指南
开发语言·javascript·node.js