In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/02 Report--
Preface
In this article you will learn:
The use of IntersectionObserver API and how to be compatible.
How to implement infinite scrolling in React Hook.
How to correctly render a list of up to 10000 elements.
Unlimited drop-down loading technology allows users to scroll in front of large chunks of content. This method is to keep loading new content as you scroll down.
When you use scrolling as the main method of discovering data, it may make your users stay on the page longer and increase user engagement. With the popularity of social media, a large amount of data is consumed by users. Wireless scrolling provides an efficient way for users to browse huge amounts of information without having to wait for the page to preload.
How to build an infinite scrolling with a good experience is a topic that every front-end will encounter whether it is a project or an interview.
The original implementation of this article comes from: Creating Infinite Scroll with 15 Elements
1. Early solution
With regard to infinite scrolling, early solutions basically relied on listening for scroll events:
Function fetchData () {fetch (path) .then (res = > doSomeThing (res.data));} window.addEventListener ('scroll', fetchData); copy code
Then calculate various .scrollTop (), .offset () .top, and so on.
Writing one by hand is also very boring. And:
Scroll events are triggered frequently, so we also need manual throttling.
There is a large amount of DOM in the scrolling element, which is easy to cause stutter.
Then came the cross-observer IntersectionObserver API, and after the framework for data-driven views such as Vue and React, a general solution for infinite scrolling came out. two。 Cross-observer: IntersectionObserver
Const box = document.querySelector ('.box'); const intersectionObserver = new IntersectionObserver ((entries) = > {entries.forEach ((item) = > {if (item.isIntersecting) {console.log ('enter the visual area');}})); intersectionObserver.observe (box); copy code
Hit the point: IntersectionObserver API is asynchronous and does not trigger synchronously with the scrolling of the target element, resulting in extremely low performance consumption.
2.1 IntersectionObserverEntry object
Here I would like to give a rough introduction to what you need: the first try of IntersectionObserve
IntersectionObserverEntry object
When the callback function is called, it is passed an array in which each object is the object currently entering or leaving the visual area (IntersectionObserverEntry object)
This object has many properties, the most commonly used of which are:
Target: the observed target element, which is a DOM node object
IsIntersecting: whether to enter the visual area
IntersectionRatio: the scale value of the intersection area and the target element, which enters the visual area. The value is greater than 0, otherwise it equals 0.
2.3 options
When calling IntersectionObserver, in addition to passing a callback function, you can also pass in an option object and configure the following attributes:
Threshold: determines when to trigger the callback function. It is an array with a threshold for each member, which defaults to [0], that is, the callback function is triggered when the intersectionRatio reaches 0. Users can customize this array. For example, [0, 0.25, 0.5, 0.75, 1] means that the callback function will be triggered when the target elements 0%, 25%, 50%, 75%, and 100% are visible.
Root: the root element for observation. The default is the browser's viewport. You can also specify a specific element. When you specify an element, the element used for observation must be a child of the specified element.
RootMargin: used to enlarge or reduce the size of windows, using the definition method of css, 10px 10px 30px 20px represents the values of top, right, bottom, and left
Const io = new IntersectionObserver ((entries) = > {console.log (entries);}, {threshold: [0,0.5], root: document.querySelector ('.container'), rootMargin: "10px 10px 30px 20px",}); copy code
2.4 observer
Observer.observer (nodeone); / / only observe nodeOne observer.observer (nodeTwo); / / observe nodeOne and nodeTwo observer.unobserve (nodeOne); / / stop watching nodeOneobserver.disconnect (); / / do not observe any node copy code
3. How to use IntersectionObserver in React Hook
Before looking at the Hooks version, let's take a look at the normal component version:
Class SlidingWindowScroll extends React.Component {this.$bottomElement = React.createRef ();... componentDidMount () {this.intiateScrollObserver ();} intiateScrollObserver = () = > {const options = {root: null, rootMargin: '0pxcodes, threshold: 0.1}; this.observer = new IntersectionObserver (this.callback, options); this.observer.observe (this.$bottomElement.current);} render () {return ()} copy code
As we all know, React 16.x introduced useRef to replace the original createRef, which is used to track DOM nodes. Then let's get started:
4. Principle
Implement a component that displays a list of n items with a fixed window size of 15 elements: that is, there are only 15 DOM nodes on the infinite scroll n element at any time.
Use relative/absolute positioning to determine the rolling position
Track two ref: top/bottom to determine whether to scroll up / down to render or not
Cut the list of data, retaining up to 15 DOM elements.
5. UseState declares state variables
Let's start writing the component SlidingWindowScrollHook:
Const THRESHOLD = 1510 Const SlidingWindowScrollHook = (props) = > {const [start, setStart] = useState (0); const [end, setEnd] = useState (THRESHOLD); const [observer, setObserver] = useState (null); / / other code.} copy code
1. Simple understanding of useState:
Const [property, method of manipulating property] = useState (default); copy code
two。 Variable analysis
Start: the first data in the currently rendered list. Default is 0.
End: the last data in the currently rendered list. Default is 15.
Observer: the currently observed view ref element
6. UseRef defines the DOM element of the trace
Const $bottomElement = useRef (); const $topElement = useRef (); copy code
Normal infinite scrolling down only needs to focus on one dom element, but since we are rendering with 15 fixed dom elements, we need to determine whether to scroll up or down.
7. Internal operation method and corresponding useEffect
Please eat with the notes:
UseEffect (() = > {/ / define observation intiateScrollObserver (); return () = > {/ / abandon observation resetObservation ()}}, [end]) / / because [end] is a synchronous refresh, just use one here. / / define observation const intiateScrollObserver = () = > {const options = {root: null, rootMargin: '0pxstories, threshold: 0.1}; const Observer = new IntersectionObserver (callback, options) / / observe the beginning and end elements if ($topElement.current) {Observer.observe ($topElement.current);} if ($bottomElement.current) {Observer.observe ($bottomElement.current) } / / set the initial value setObserver (Observer)} / / the specific callback of cross observation, observe each node, and process the real-time header and tail element index const callback = (entries, observer) = > {entries.forEach ((entry, index) = > {const listLength = props.list.length; / / scroll down, refresh the data if (entry.isIntersecting & & entry.target.id = = "bottom") {const maxStartIndex = listLength-1-THRESHOLD / / current header index const maxEndIndex = listLength-1; / / current tail index const newEnd = (end + 10) 0? Start-10: 0); / / the minimum value of the header element index is 0 setStart (newStart) setEnd (newEnd)}});} / / abandon viewing when scrolling is stopped const resetObservation = () = > {observer & & observer.unobserve ($bottomElement.current); observer & & observer.unobserve ($topElement.current);} / / when rendering, the header and tail ref process const getReference = (index, isLastIndex) = > {if (index = 0) return $topElement; if (isLastIndex) return $bottomElement; return null;} copy code
8. Rendering interface
Const {list, height} = props; / / data, node height const updatedList = list.slice (start, end); / / data cutting const lastIndex = updatedList.length-1; return ({updatedList.map ((item, index) = > {const top = (index + start)) + 'px'; / / const refVal = getReference (index, index = lastIndex) based on relative & absolute positioning; / / head-tail ref const id = index = 0? 'top': (index = lastIndex? 'bottom':'); / / bind ID return ({item.value});}); copy code
9. How to use
App.js:
Import React from 'react';import'. / App.css';import {SlidingWindowScrollHook} from ". / SlidingWindowScrollHook"; import MY_ENDLESS_LIST from'. / Constants';function App () {return (15 elements achieve infinite scrolling);} export default App; copy code
Define the data Constants.js:
Const MY_ENDLESS_LIST = [{key: 1, value:'A'}, {key: 2, value:'B'}, {key: 3, value:'C'}, / / Don't paste it in the middle. {key: 45, value: 'AS'}] copy the code
SlidingWindowScrollHook.js:
Import React, {useState, useEffect, useRef} from "react"; const THRESHOLD = 15 const Const SlidingWindowScrollHook = (props) = > {const [start, setStart] = useState (0); const [end, setEnd] = useState (THRESHOLD); const [observer, setObserver] = useState (null); const $bottomElement = useRef (); const $topElement = useRef (); useEffect () = > {intiateScrollObserver () Return () = > {resetObservation ()} / / eslint-disable-next-line react-hooks/exhaustive-deps}, [start, end]) const intiateScrollObserver = () = > {const options = {root: null, rootMargin: '0pxrabbit, threshold: 0.1}; const Observer = new IntersectionObserver (callback, options) if ($topElement.current) {Observer.observe ($topElement.current);} if ($bottomElement.current) {Observer.observe ($bottomElement.current) } setObserver (Observer)} const callback = (entries, observer) = > {entries.forEach ((entry, index) = > {const listLength = props.list.length; / / Scroll Down if (entry.isIntersecting & & entry.target.id = "bottom") {const maxStartIndex = listLength-1-THRESHOLD; / / Maximum index value `start` can take const maxEndIndex = listLength-1; / / Maximum index value `end` can take const newEnd = (end + 10) 0? Start-10: 0); setStart (newStart) setEnd (newEnd)}});} const resetObservation = () = > {observer & & observer.unobserve ($bottomElement.current); observer & & observer.unobserve ($topElement.current);} const getReference = (index, isLastIndex) = > {if (index = 0) return $topElement; if (isLastIndex) return $bottomElement; return null;} const {list, height} = props; const updatedList = list.slice (start, end); const lastIndex = updatedList.length-1 Return ({updatedList.map ((item, index) = > {const top = (height * (index + start)) + 'px'; const refVal = getReference (index, index = lastIndex); const id = index = 0? 'top': (index = lastIndex? 'bottom':'); return ({item.value});})});} export {SlidingWindowScrollHook}; copy the code
And a few styles:
.li-card {display: flex; justify-content: center; list-style: none; box-shadow: 2px 2px 9px 0px # bbb; padding: 70px 0; margin-bottom: 20px; border-radius: 10px; position: absolute; width: 80%;} copy the code
Then you can play slowly.
10. Compatibility processing
IntersectionObserver is not compatible with Safari?
Don't panic, we have the polyfill version.
340000 downloads a week, don't worry about it, brothers.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.