Penatalan Tak Terhingga Tanpa Usaha: Cara Melaksanakan Lazy Loading dengan Pemerhati Persimpangan

王林
Lepaskan: 2024-08-26 21:34:06
asal
739 orang telah melayarinya

Bagaimanakah kita boleh mengesan dengan cekap dan mudah apabila elemen pada halaman web menjadi kelihatan atau tersembunyi, tanpa memperlahankan halaman atau menulis kod kompleks untuk mengendalikan acara tatal dan pengiraan keterlihatan, terutamanya dalam kes seperti memuatkan imej hanya apabila diperlukan (malas- memuatkan), mencipta skrol tanpa had atau mencetuskan animasi apabila kandungan muncul?

pengenalan

Sebagai pembangun, kami selalunya mahu memuatkan kandungan seperti imej atau artikel baharu, hanya apabila ia kelihatan pada skrin pengguna untuk menjimatkan lebar jalur dan mempertingkatkan masa memuatkan halaman. Walau bagaimanapun, ini boleh menjadi rumit kerana terdapat keperluan untuk mengetahui dengan tepat apabila unsur-unsur ini kelihatan apabila pengguna menatal pada halaman web.

Kaedah Tradisional Menambah EventListener pada Acara Tatal

Secara tradisinya, ini memerlukan menyediakan pendengar acara tatal dan mengira kedudukan elemen secara manual, yang boleh membawa kepada prestasi yang perlahan dan kikuk, terutamanya pada halaman dengan banyak kandungan atau pada peranti dengan kuasa pemprosesan terhad.

// Function to fetch data from an API
function fetchData() {
  console.log('Fetching more data...');

  // Simulate an API request using fetch
  fetch('https://jsonplaceholder.typicode.com/posts?_limit=5&_page=1')
    .then(response => response.json())
    .then(data => {
      // Display the fetched data on the page
      })
    .catch(error => console.error('Error fetching data:', error));
}

// Function to check if the user is near the bottom of the page
function checkScrollPosition() {
  const scrollPosition = window.innerHeight + window.scrollY;
  const threshold = document.body.offsetHeight - 100;

  if (scrollPosition >= threshold) {
    fetchData();
  }
}

// Add the scroll event listener to the window object
window.addEventListener('scroll', checkScrollPosition);

// Initial call to load some data when the page first loads
fetchData();
Salin selepas log masuk

Pendengar acara yang ditambahkan mungkin kelihatan mudah tetapi, anda akan melihat isu yang datang bersamanya apabila anda bekerja pada halaman dengan banyak data. Pendengar acara direka bentuk untuk menyala beberapa kali dalam satu saat untuk mencapai pendengaran acara, sementara ini berfungsi, ia mempengaruhi prestasi halaman kerana JavaScript ialah bahasa pengaturcaraan satu utas. Juga untuk mencapai kesan yang sama yang boleh dilakukan oleh pemerhati persimpangan, pembangun perlu mengambil perhatian tentang dimensi viewport dan menambah pengiraan yang akan dilakukan secara tetap yang masih menjejaskan prestasi.

Cabarannya ialah untuk mengesan perubahan keterlihatan tanpa menulis kod kompleks atau membuat halaman ketinggalan. Menyelesaikan perkara ini memerlukan cara yang lebih cekap untuk memantau keterlihatan yang tidak melambatkan penyemak imbas dengan pemeriksaan dan pengiraan berterusan. Di sinilah Intersection Observer API masuk, menawarkan penyelesaian yang lebih mudah dan mesra prestasi kepada cabaran pengesanan keterlihatan ini.

API Intersection Observer ialah alat yang berkuasa dalam pembangunan web yang menyelesaikan cabaran ini. Alat ini memudahkan pengesanan apabila elemen pada halaman web memasuki atau keluar dari kawasan yang boleh dilihat (port view tetingkap) tanpa pengiraan yang rumit.

Daripada pemeriksaan acara tatal berterusan, yang boleh menjejaskan prestasi ciri utas CPU tunggal JavaScript, API membenarkan penyemak imbas mengendalikan pengesanan keterlihatan secara automatik, membolehkan pelaksanaan ciri yang lebih lancar seperti imej malas memuatkan, menatal tanpa had, animasi yang dicetuskan oleh elemen keterlihatan dan melaporkan keterlihatan iklan web untuk mengira hasil iklan. Dengan memunggah tugasan ini ke penyemak imbas, Intersection Observer API membantu memastikan halaman cepat dan cekap, terutamanya pada tapak yang kompleks atau padat kandungan. Selain itu, Intersection Observer API adalah serasi dengan semua penyemak imbas, menjadikannya penyelesaian yang mahir untuk menjejaki acara tatal tanpa sebarang pertukaran.

Objektif

Menjelang akhir artikel ini, anda akan:

  • Tahu cara menggunakan Intersection Observer API untuk menyemak apabila elemen muncul.
  • Fahami istilah dan sintaks Intersection Observer API.
  • Ketahui cara mengambil data daripada API apabila elemen itu kelihatan.
  • Dapat menghuraikan data JSON dan menambahkannya pada struktur HTML anda.

Siaran ini akan menunjukkan kepada anda cara menggunakan Intersection Observer API dan fungsi ambil () JavaScript untuk mendapatkan data dan mengemas kini halaman anda dengannya. Kami akan melalui langkah-langkah untuk membina pengalaman web yang cekap dan menarik. Jom mulakan!

Memahami Intersection Observer API, Konsep dan Penggunaan

Pemerhati persimpangan

Pemerhati Persimpangan biasanya menjejaki apabila bahagian tertentu muncul pada skrin. Ia menentukan sama ada elemen memenuhi port pandangan atau bahagian skrin yang boleh ditatal. Anda mesti menetapkan pilihan akar pemerhati kepada null untuk melihat perubahan dalam keterlihatan mengenai keseluruhan skrin. Ini membantu menjejaki item apabila ia menatal ke paparan.
Walaupun perkataan "root" mungkin kedengaran asing, anda akan faham sebabnya semasa anda membacanya?.

API berfungsi dengan cara yang sama tidak kira sama ada anda menggunakan port pandang atau elemen lain sebagai punca; ia memanggil fungsi panggil balik yang anda bekalkan setiap kali keterlihatan elemen sasaran berubah ke titik di mana ia melepasi darjah persilangan yang sesuai dengan akar.

Tahap persilangan antara elemen sasaran dan puncanya ialah nisbah persilangan. Ini ialah perwakilan peratusan elemen sasaran yang boleh dilihat sebagai nilai antara 0.0 dan 1.0.

Creating an intersection observer

To create the intersection observer, you'll call its constructor and pass an option object for behaviour and a callback function to be invoked whenever a threshold is crossed in one direction or the other:

let options = {
  root: document.querySelector("#ObservableArea"),
  rootMargin: "0px",
  threshold: 1.0,
};

let observer = new IntersectionObserver(callback, options);

//A threshold of 1.0 means that when 100% of the target is visible within the element specified by the root option, the callback is invoked.

Salin selepas log masuk

Intersection observer options object

The options object passed into the IntersectionObserver() constructor lets you control the trigger and behaviour of the observer's callback to be invoked. The Options object contains the following keys:

root:
The element that is used as the viewport for checking the visibility of the target. It must be a scrollable container or ancestor of the target. Intersection Observer defaults to the browser viewport if not specified or if null.

rootMargin:
Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). The values can be percentages. This set of values serves to grow or shrink each side of the root element's bounding box before computing intersections. Defaults to all zeros.

threshold:
The observer's callback should be executed at a specific % of the target's visibility, indicated by a single or array of numbers. Use a value of 0.5 if you wish to detect only when visibility rises above 50%. To ensure that the callback is executed each time visibility increases by 25%, you can supply the array [0, 0.25, 0.5, 0.75, 1]. The default is 0, which means that the callback will be executed as soon as even a single pixel is displayed. If the value is 1.0, then all pixels must be visible for the threshold to be deemed passed.

Observing a target element

After creating the observer, you need a target element to be observed.

let target = document.querySelector("#target");
observer.observe(target);

// the callback we set up for the observer will be executed now for the first time
// it waits until we assign a target to our observer (even if the target is currently not visible)
Salin selepas log masuk

Whenever the target meets a threshold specified for the IntersectionObserver, the callback is invoked. The callback receives a list of IntersectionObserverEntry objects and the observer:

let callback = (entries, observer) => {
  entries.forEach((entry) => {
    // Each entry describes an intersection change for one observed
    // target element:
    //   entry.boundingClientRect
    //   entry.intersectionRatio
    //   entry.intersectionRect
    //   entry.isIntersecting
    //   entry.rootBounds
    //   entry.target
    //   entry.time
  });
};

Salin selepas log masuk

The list of entries received by the callback includes one entry for each target which reported a change in its intersection status. Check the value of the isIntersecting property to see if the entry represents an element that currently intersects with the root.

N/B!
Be aware that your callback is executed on the main thread. It should operate as quickly as possible; if anything time-consuming needs to be done, use Window.requestIdleCallback().

Also, note that if you specified the root option, the target must be a descendant of the root element.

Project Setup

Now you've got the full gist about intersection observer, I'm excited to get started with the project ?.
In setting up this project, Microsoft Visual Studio Code (VS Code) was used but if you have another text editor or IDE you love, feel free to use that, we won’t judge! ?

However, the steps and procedure to follow are easy, and setting up your project is as easy as taking candy from a baby; that challenge required almost no effort at all. By the end, you'll be able to track when elements appear or disappear on your screen.

You’ll just need three files to get started:

  • index.html
  • styles.css
  • script.js

The simplicity of this setup is intentional, as it is designed for beginners. But don't worry—once you’re comfortable, you can use the Intersection Observer in more complex projects utilizing frameworks like React or Vue.

Create a Project Directory:

If you're using a Linux or Mac machine copy and paste the code below to your terminal/shell.

#create a directory and enter the
mkdir project && cd project

#create the files and open VS code
touch index.html script.js styles.css

#open the current directory on VS Code
code .
Salin selepas log masuk

On Windows, just open VS code on your device, press Ctrl+Shift+N to create a new window, then click on open Folder at the start tab, when the File Explorer opens, create a new folder then click on the new folder and select it. If you don't see the explorer in VS code press Ctrl+Shift+E to open the explorer then click on Create a new file. Give the files any name you want but for the sake of the article I used index.html, style.css and script.js.

  • index.html

After creating your index.html, make sure it looks like the file below

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Movie List with Infinite Scrolling</title>
   <link rel="stylesheet" href="style.css">
</head>
<body>
    <input type="text" value="" placeholder="enter movie title to search" id="searchInput">
    <button id="search">Search</button>
    <div class="movie-container" id="movieContainer"></div>
    <div id="loading">Loading...</div>

    <script src="script.js"></script>
</body>
</html>

Salin selepas log masuk
  • styles.css

Just follow along with the code below:

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
.movie-container {
    width: 80%;
    max-width: 800px;
    margin-top: 20px;
}
.movie-item {
    display: flex;
    border: 1px solid #ddd;
    margin-bottom: 10px;
    padding: 10px;
    border-radius: 5px;
    background-color: #f9f9f9;
}
.movie-item img {
    max-width: 100px;
    margin-right: 20px;
}
.movie-info {
    display: flex;
    flex-direction: column;
}
.movie-info h3 {
    margin: 0;
    margin-bottom: 10px;
}
.movie-info p {
    margin: 0;
}
#loading {
    text-align: center;
    margin-top: 20px;
    display: none;
}

Salin selepas log masuk
  • script.js
const movieContainer = document.getElementById('movieContainer');
const loading = document.getElementById('loading');
const search = document.getElementById('search');
const searchInput = document.getElementById('searchInput');
let currentPage = 1;
let observer;

const API_KEY = '3676363636'; // Replace with a real API key

async function fetchMovies(query, page) {
    loading.style.display = 'block';

    const API_URL = `http://www.omdbapi.com/?s=${query}&apikey=${API_KEY}&page=${page}`;
    const response = await fetch(API_URL);
    const {Search} = await response.json();

    loading.style.display = 'none';

    displayMovies(Search); // Assuming the API returns an array of movies
}

function displayMovies(movies) {
    movies.forEach(movie => {
        const movieItem = document.createElement('div');
        movieItem.classList.add('movie-item');

        movieItem.innerHTML = `
            <img src="${movie.Poster}" alt="${movie.Title}">
            <div class="movie-info">
                <h3>${movie.Title}</h3>
                <p><strong>imdbID:</strong> ${movie.imdbID}</p>
                <p><strong>Year:</strong> ${movie.Year}</p>
            </div>
        `;

        movieContainer.appendChild(movieItem);
    });

    // Reattach the observer to the last movie item
    if (observer) observer.disconnect();
    const lastMovieItem = document.querySelector('.movie-item:last-child');
    if (lastMovieItem) observer.observe(lastMovieItem);
}

// Set up the Intersection Observer
observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting) {
        currentPage++;
        const query = searchInput.value.trim();
        if (query) {
            fetchMovies(query, currentPage);
        }
    }
}, { threshold: 1 });

search.addEventListener('click', () => {
    currentPage = 1; // Reset to the first page on new search
    movieContainer.innerHTML = ''; // Clear previous results
    const query = searchInput.value.trim();
    if (query) {
        fetchMovies(query, currentPage);
    }
});

Salin selepas log masuk

Code Explanation
The index.html is a simple HTML with a head, body, an input to get a query from the user, and a button that the user clicks to fire an action, this action is taken over by the script tag, which calls a function appending the users' query to be fetched by the OMDB API. I used OMDB just for simplicity and illustration, but like I said before, the project structure isn't rigid so readers can choose any method preferred by them.

The style.css contains simple classes for styling the fetched data after being parsed by the script tag. I would not go into details of the styles file as this is not the reason for the article, but developers can always check out w3schools for more tutorials on CSS.

The script.js file is the holy grail of the whole read, for beginners, I'll break the contents of this file into small explainable chunks.

Variable Definition and Elements Selection:

const movieContainer = document.getElementById('movieContainer');
const loading = document.getElementById('loading');
const search = document.getElementById('search');
const searchInput = document.getElementById('searchInput');
let currentPage = 1;
let observer;

const API_KEY = '3676363636'; // Replace with your real API key

Salin selepas log masuk

The above code first selects the elements in the index.html and also creates some local variables that will be used in the script.
The currentPage variable is like a page state in the application, that increases as the observer detects an intersection, it is used for querying the OMDB API. The observer variable is defined using the let keyword to be assigned to the IntersectionObserver() constructor function in the later part of the script.

Fetching and Parsing Fetched Data:

async function fetchMovies(query, page) {
    loading.style.display = 'block';

    const API_URL = `http://www.omdbapi.com/?s=${query}&apikey=${API_KEY}&page=${page}`;
    const response = await fetch(API_URL);
    const {Search} = await response.json();

    loading.style.display = 'none';

    displayMovies(Search); // Assuming the API returns an array of movies
}

function displayMovies(movies) {
    movies.forEach(movie => {
        const movieItem = document.createElement('div');
        movieItem.classList.add('movie-item');

        movieItem.innerHTML = `
            <img src="${movie.Poster}" alt="${movie.Title}">
            <div class="movie-info">
                <h3>${movie.Title}</h3>
                <p><strong>imdbID:</strong> ${movie.imdbID}</p>
                <p><strong>Year:</strong> ${movie.Year}</p>
            </div>
        `;

        movieContainer.appendChild(movieItem);
    });

    //observer code here
}
Salin selepas log masuk

In the code above, the fetchMovies() function contains the query and page parameters, first, the loading element in the HTML is made visible with the display=block, and then API_URL is a variable that holds the preferred API service in string format.
Depending on the API you want to use, some of them offer their services to registered users only. For services like OMDB you have to create an account with them where you'll be given a key upon completion of the registration. That key will be used in the API_URL string. OMDB API sends an array of movies containing 10 items only, the page variable is used to query the API to send the next 10 items after viewing the previous ones. If you noticed I interpolated the string using ${} where I added the query from the user input and also my key from the OMDB movie Service.

const API_URL = `http://www.omdbapi.com/?s=${query}&apikey=${API_KEY}&page=${page}`;
Salin selepas log masuk

The response variable awaits the response after fetching the API_URL, the data variable parses the response to JSON format using the .json() method on the response variable.
Once the data is fetched the display of the loading element is set to none to hide the loading element.
After that, the displayMovies is called with the destructured Search from the returned JSON. The work of the display function is to accept an array of movies in JSON format and parse each movie to an HTML template containing the movie poster and details of each movie in the array.

// Reattach the observer to the last movie item
    if (observer) observer.disconnect();
    const lastMovieItem = document.querySelector('.movie-item:last-child');
    if (lastMovieItem) observer.observe(lastMovieItem);
Salin selepas log masuk

This code is attached to the displayMovies() function, I'm explaining it separately for adept understanding. In the above code, the observer is disconnected from the last-item queried and attached to the current last-item. This is to ensure the observer is up-to-date at each instance of observing.

// Set up the Intersection Observer
observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting) {
        currentPage++;
        const query = searchInput.value.trim();
        if (query) {
            fetchMovies(query, currentPage);
        }
    }
}, { threshold: 1 });

Salin selepas log masuk

This is where the IntersectionObserver constructor function is defined. This function continues the query with the current page after the user initially fires the click event. This enables the application to fetch movie items when they need to be seen in the view-port rather than clogging the application with data, that the user may not even reach before finding the information they are looking for in this case a movie.

search.addEventListener('click', () => {
    currentPage = 1; // Reset to the first page on the new search
    movieContainer.innerHTML = ''; // Clear previous results
    const query = searchInput.value.trim();
    if (query) {
        fetchMovies(query, currentPage);
    }
});
Salin selepas log masuk

This last code is a simple code that adds an event listener to listen for the click event on the search button element. This is like the entry point of the application, as the user enters input in the search box and clicks on the search button, the function attached to the event listener function is invoked. First, it resets the current page to 1, then clears the parsed data from the previous query. Lastly, it fetches the new query with its current page as 1. The intersection observer continues the fetching queries from the API_URL, after reaching the last-item of the parsed HTML from the Search data returned in the query.

Effortless Infinite Scrolling: How to Implement Lazy Loading with Intersection Observer

The GIF above shows how the application works, and how the data are fetched when the user scrolls to the last movie item, this is performed by the Intersection Observer calling the fetch function after the user has queried the API.

Kesimpulan

Projek menunjukkan cara menggunakan Pemerhati Persimpangan untuk memerhati kanak-kanak atau elemen sasaran oleh elemen induk. Pemerhati adalah seperti mata yang diletakkan pada kotak dengan kotak yang lebih kecil, kini apabila kotak yang lebih kecil kelihatan (bersilang) fungsi dipanggil. Dalam artikel ini, fungsi yang digunakan terus mengambil pertanyaan oleh pengguna yang menambahkan halaman semasa sehingga penghujung data yang diambil dan dihuraikan dalam tatasusunan.

Seluruh sebab pemerhati adalah untuk memerhati item terakhir sebelum mengambil semula dari API_URL, kaedah pemuatan malas kedua-dua data dan imej poster ini mengurangkan pembaziran lebar jalur, meningkatkan masa muat halaman dan yang lebih penting menunjukkan pengguna sahaja apa yang mereka ingin tanyakan. Sebagai contoh, pengguna bertanya kepada "John Wick", tetapi idea keseluruhannya adalah untuk mendapatkan "John Wick Parabellum" sebelum halaman menunjukkan semua filem John Wick, pengguna mesti telah mengetahui filem yang dimaksudkan sebelum carian.

Jika dibandingkan dengan pendengar acara tatal, Intersection Observer API adalah lebih cekap dan lebih mudah digunakan. Ini kerana tidak seperti pendengar acara tatal, yang sentiasa menyala semasa anda menatal dan boleh memperlahankan halaman anda, Pemerhati Persimpangan hanya menyemak keterlihatan elemen apabila perlu, meningkatkan prestasi. Ia secara automatik mengendalikan apabila elemen muncul, membuat tugas seperti memuatkan imej malas, mencetuskan animasi dan menatal tanpa had dengan lebih mudah dan pantas untuk dilaksanakan. Anda tidak perlu risau tentang helah pengekodan tambahan untuk mengurus kemas kini yang kerap, dan ia berfungsi secara konsisten merentas penyemak imbas yang berbeza.

Atas ialah kandungan terperinci Penatalan Tak Terhingga Tanpa Usaha: Cara Melaksanakan Lazy Loading dengan Pemerhati Persimpangan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan