>  기사  >  웹 프론트엔드  >  vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

青灯夜游
青灯夜游원래의
2022-11-29 19:09:086319검색

세 가지 방법: 1. offsetTop 및 scrollTop을 사용하여 요소의 위치를 ​​얻고 viewPortHeight(뷰 포트 거리)보다 작거나 같은지 확인합니다. 2. getBoundingClientRect()를 사용하여 판단합니다. 구문은 "element object.getBoundingClientRect()"입니다. 3. IntersectionObserver를 사용하여 판단하고 지정된 요소와 보이는 영역이 겹치는지 확인하십시오.

vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

이 튜토리얼의 운영 환경: windows7 시스템, vue3 버전, DELL G3 컴퓨터.

가시 영역이란 무엇인가요?

가시 영역은 아래와 같이 우리가 웹을 탐색하는 데 사용하는 장치에서 육안으로 볼 수 있는 영역입니다.

vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

우리는 일상적인 개발에서 종종 결정해야 할 사항이 있습니다. 대상 요소가 창 안에 있는지 또는 창 안에 있는지 여부 보기 창 사이의 거리는 값(예: 100px)보다 작으므로 다음과 같이 일반적으로 사용되는 일부 기능을 수행합니다.

  • 이미지의 지연 로딩
  • 무한 스크롤 목록
  • 광고 요소의 노출 계산
  • 클릭 가능한 링크 미리 로드

요소가 가시 영역에 있는지 확인하는 세 가지 방법

요소가 가시 영역에 있는지 확인하려면 일반적으로 세 가지 방법이 있습니다. 사용된 메소드:

  • offsetTop, scrollTop

  • getBoundingClientRect

  • Intersection Observer

메서드 1, offsetTop

offsetTop, 사이의 픽셀 거리 요소의 위쪽 외부 테두리와 포함 요소의 위쪽 내부 테두리, 기타 오프셋 속성은 다음과 같습니다. offsetTop,元素的上外边框至包含元素的上内边框之间的像素距离,其他offset属性如下图所示:

vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

下面再来了解下clientWidthclientHeight

  • clientWidth:元素内容区宽度加上左右内边距宽度,即clientWidth = content + padding
  • clientHeight:元素内容区高度加上上下内边距高度,即clientHeight = content + padding

这里可以看到client元素都不包括外边距

最后,关于scroll系列的属性如下:

  • scrollWidthscrollHeight 主要用于确定元素内容的实际大小

  • scrollLeftscrollTop 属性既可以确定元素当前滚动的状态,也可以设置元素的滚动位置

    • 垂直滚动 scrollTop > 0
    • 水平滚动 scrollLeft > 0
  • 将元素的 scrollLeftscrollTop 设置为 0,可以重置元素的滚动位置

注意

  • 上述属性都是只读的,每次访问都要重新开始

下面再看看如何实现判断:

公式如下:

el.offsetTop - document.documentElement.scrollTop <= viewPortHeight

代码实现:

function isInViewPortOfOne (el) {
    // viewPortHeight 兼容所有浏览器写法
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
    const offsetTop = el.offsetTop
    const scrollTop = document.documentElement.scrollTop
    const top = offsetTop - scrollTop
    return top <= viewPortHeight
}

方法2:getBoundingClientRect

返回值是一个 DOMRect对象,拥有left, top, right, bottom, x, y, width, 和 height属性。【学习视频分享:vue视频教程web前端视频

const target = document.querySelector(&#39;.target&#39;);
const clientRect = target.getBoundingClientRect();
console.log(clientRect);

// {
//   bottom: 556.21875,
//   height: 393.59375,
//   left: 333,
//   right: 1017,
//   top: 162.625,
//   width: 684
// }

属性对应的关系图如下所示:

vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

当页面发生滚动的时候,topleft

vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?

clientWidth, <code>clientHeight:
  • clientWidth: 요소 콘텐츠에 대해 자세히 알아보세요. 영역 너비에 왼쪽 및 오른쪽 패딩 너비를 더한 값, 즉 clientWidth = content + padding
  • clientHeight: 요소 콘텐츠 영역의 높이에 상단 및 하단의 높이를 더한 값입니다. 패딩, 즉 clientHeight = content + padding
  • 여기에서 client를 볼 수 있습니다. 어떤 요소에도 여백이 포함되어 있지 않습니다
마지막으로 스크롤의 속성 시리즈는 다음과 같습니다:

scrollWidthscrollHeight는 주로 요소 콘텐츠의 실제 크기를 결정하는 데 사용됩니다🎜🎜🎜🎜scrollLeft scrollTop 속성은 모두 요소의 현재 스크롤 상태를 결정하고 요소의 스크롤 위치를 설정할 수 있습니다🎜🎜🎜🎜🎜세로 스크롤 scrollTop > 🎜🎜가로로 스크롤 scrollLeft > 0🎜🎜🎜🎜🎜요소의 scrollLeftscrollTop을 0으로 설정하여 스크롤 위치를 재설정합니다. element🎜🎜🎜🎜🎜Note🎜🎜🎜🎜위 속성은 읽기 전용이며 방문할 때마다 처음부터 다시 시작해야 합니다🎜🎜🎜판단 구현 방법을 살펴보겠습니다.🎜🎜 수식은 다음과 같습니다. : 🎜🎜
function isInViewPort(element) {
  const viewWidth = window.innerWidth || document.documentElement.clientWidth;
  const viewHeight = window.innerHeight || document.documentElement.clientHeight;
  const {
    top,
    right,
    bottom,
    left,
  } = element.getBoundingClientRect();

  return (
    top >= 0 &&
    left >= 0 &&
    right <= viewWidth &&
    bottom <= viewHeight
  );
}
🎜🎜코드 구현: 🎜🎜
const options = {
  // 表示重叠面积占被观察者的比例,从 0 - 1 取值,
  // 1 表示完全被包含
  threshold: 1.0, 
  root:document.querySelector(&#39;#scrollArea&#39;) // 必须是目标元素的父级元素
};

const callback = (entries, observer) => { ....}

const observer = new IntersectionObserver(callback, options);
🎜

🎜🎜방법 2: getBoundingClientRect🎜🎜🎜🎜반환 값은 left가 포함된 <code>DOMRect 객체입니다. , 상단, 오른쪽, 하단, x, y > , 너비높이 속성입니다. [학습 동영상 공유: vue 동영상 튜토리얼, 웹 프런트엔드 동영상]🎜🎜
// 上段代码中被省略的 callback
const callback = function(entries, observer) { 
    entries.forEach(entry => {
        entry.time;               // 触发的时间
        entry.rootBounds;         // 根元素的位置矩形,这种情况下为视窗位置
        entry.boundingClientRect; // 被观察者的位置举行
        entry.intersectionRect;   // 重叠区域的位置矩形
        entry.intersectionRatio;  // 重叠区域占被观察者面积的比例(被观察者不是矩形时也按照矩形计算)
        entry.target;             // 被观察者
    });
};
🎜🎜 속성 대응 관계도는 다음과 같습니다. 🎜🎜vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?🎜🎜페이지가 스크롤되면 topleft 속성 값이 그에 따라 변경됩니다🎜🎜요소가 창 내에 있는 경우, 그러면 다음 네 가지 조건이 충족되어야 합니다. 🎜🎜🎜top은 0🎜🎜left는 0🎜🎜bottom은 창 높이보다 작거나 같습니다🎜🎜right는 0보다 작거나 같습니다. 창 너비와 동일🎜🎜🎜구현 코드는 다음과 같습니다. 🎜🎜
const target = document.querySelector(&#39;.target&#39;);
observer.observe(target);
🎜

方法3:Intersection Observer

Intersection Observer 即重叠观察者,从这个命名就可以看出它用于判断两个元素是否重叠,因为不用进行事件的监听,性能方面相比getBoundingClientRect会好很多

使用步骤主要分为两步:创建观察者和传入被观察者

创建观察者

const options = {
  // 表示重叠面积占被观察者的比例,从 0 - 1 取值,
  // 1 表示完全被包含
  threshold: 1.0, 
  root:document.querySelector(&#39;#scrollArea&#39;) // 必须是目标元素的父级元素
};

const callback = (entries, observer) => { ....}

const observer = new IntersectionObserver(callback, options);

通过new IntersectionObserver创建了观察者 observer,传入的参数 callback 在重叠比例超过 threshold 时会被执行`

关于callback回调函数常用属性如下:

// 上段代码中被省略的 callback
const callback = function(entries, observer) { 
    entries.forEach(entry => {
        entry.time;               // 触发的时间
        entry.rootBounds;         // 根元素的位置矩形,这种情况下为视窗位置
        entry.boundingClientRect; // 被观察者的位置举行
        entry.intersectionRect;   // 重叠区域的位置矩形
        entry.intersectionRatio;  // 重叠区域占被观察者面积的比例(被观察者不是矩形时也按照矩形计算)
        entry.target;             // 被观察者
    });
};
传入被观察者

通过 observer.observe(target) 这一行代码即可简单的注册被观察者

const target = document.querySelector(&#39;.target&#39;);
observer.observe(target);

案例分析

实现:创建了一个十万个节点的长列表,当节点滚入到视窗中时,背景就会从红色变为黄色

Html结构如下:

<div class="container"></div>

css样式如下:

.container {
    display: flex;
    flex-wrap: wrap;
}
.target {
    margin: 5px;
    width: 20px;
    height: 20px;
    background: red;
}

container插入1000个元素

const $container = $(".container");

// 插入 100000 个 <div class="target"></div>
function createTargets() {
  const htmlString = new Array(100000)
    .fill(&#39;<div class="target"></div>&#39;)
    .join("");
  $container.html(htmlString);
}

这里,首先使用getBoundingClientRect方法进行判断元素是否在可视区域

function isInViewPort(element) {
    const viewWidth = window.innerWidth || document.documentElement.clientWidth;
    const viewHeight =
          window.innerHeight || document.documentElement.clientHeight;
    const { top, right, bottom, left } = element.getBoundingClientRect();

    return top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight;
}

然后开始监听scroll事件,判断页面上哪些元素在可视区域中,如果在可视区域中则将背景颜色设置为yellow

$(window).on("scroll", () => {
    console.log("scroll !");
    $targets.each((index, element) => {
        if (isInViewPort(element)) {
            $(element).css("background-color", "yellow");
        }
    });
});

通过上述方式,可以看到可视区域颜色会变成黄色了,但是可以明显看到有卡顿的现象,原因在于我们绑定了scroll事件,scroll事件伴随了大量的计算,会造成资源方面的浪费

下面通过Intersection Observer的形式同样实现相同的功能

首先创建一个观察者

const observer = new IntersectionObserver(getYellow, { threshold: 1.0 });

getYellow回调函数实现对背景颜色改变,如下:

function getYellow(entries, observer) {
    entries.forEach(entry => {
        $(entry.target).css("background-color", "yellow");
    });
}

最后传入观察者,即.target元素

$targets.each((index, element) => {
    observer.observe(element);
});
可以看到功能同样完成,并且页面不会出现卡顿的情况

위 내용은 vue는 요소가 가시 영역에 있는지 어떻게 확인합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.