首頁 >web前端 >前端問答 >vue怎麼判斷元素是否在視覺區域

vue怎麼判斷元素是否在視覺區域

青灯夜游
青灯夜游原創
2022-11-29 19:09:086374瀏覽

三種方法:1.利用offsetTop和scrollTop取得元素的位置,判斷是否小於等於viewPortHeight(視圖埠距離)即可。 2.利用getBoundingClientRect()判斷,語法「元素物件.getBoundingClientRect()」。 3.利用IntersectionObserver判斷,只需要檢查指定元素和視覺區域是否重疊即可。

vue怎麼判斷元素是否在視覺區域

本教學操作環境:windows7系統、vue3版,DELL G3電腦。

視覺區域是什麼

可視區域即我們瀏覽網頁的裝置肉眼可見的區域,如下圖

vue怎麼判斷元素是否在視覺區域

在日常開發中,我們經常需要判斷目標元素是否在視窗之內或和視窗的距離小於一個值(例如100 px),從而實現一些常用的功能,例如:

  • 圖片的懶​​加載
  • 列表的無限滾動
  • 計算廣告元素的曝光情況
  • 可點擊連結的預先載入

判斷元素是否在視覺區域的三種方式

判斷一個元素是否在視覺區域,我們常用的有三種方法:

  • offsetTop、scrollTop

  • getBoundingClientRect

  • Intersection Observer

方法1 、offsetTop、scrollTop

offsetTop,元素的上外邊框至包含元素的上內邊框之間的像素距離,其他offset屬性如下圖所示:

vue怎麼判斷元素是否在視覺區域

下面再來了解下方clientWidthclientHeight

##clientWidth

:元素內容區寬度加上左右內邊距寬度,即
    clientWidth = content padding
  • clientHeight:元素內容區高度加上上下內邊距高度,即clientHeight = content padding

  • 這裡可以看到client元素都不包含外邊距#最後,關於

    scroll
  • 系列的屬性如下:
    • scrollWidth
    • scrollHeight 主要用於確定元素內容的實際大小
  • scrollLeft

    scrollTop 屬性既可以決定元素目前捲動的狀態,也可以設定元素的捲動位置

#垂直捲動

scrollTop > 0

#水平捲動
    scrollLeft > 0

將元素的

scrollLeft
scrollTop

設為0,可以重置元素的捲動位置

#注意上述屬性都是唯讀的,每次存取都要重新開始

#下面再看看如何實作判斷:公式如下:<pre class="brush:js;toolbar:false;">el.offsetTop - document.documentElement.scrollTop &lt;= viewPortHeight</pre>程式碼實作:<pre class="brush:js;toolbar:false;">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 &lt;= viewPortHeight }</pre>方法2:getBoundingClientRect #傳回值是一個DOMRect對象,擁有left, top

,
right
,

bottom

,

xvue怎麼判斷元素是否在視覺區域,

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
    // }
  • 屬性對應的關係圖如下:
當頁面發生捲動的時候,

top

left
屬性值都會隨之改變######如果一個元素在視窗之內的話,那麼它一定滿足下面四個條件:#########top 大於等於0######left 大於等於0######bottom 小於等於視窗高度## ####right 小於等於視窗寬度#########實作程式碼如下:######
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
  );
}
###

方法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