background
In a recent business, the product made a request to add a back to the top button in the bottom right corner of the page. Since the front-end UI framework uses Ant Design Pro, it’s natural to look for similar components in the Ant Design component library. Ant Design provides a BackTop component that returns to the top of the page. You introduce this component into your project, find that you can’t render it in your project code, discard it, and implement a back to the top button yourself.
Realize the button
The back to Top button is usually fixed in the lower right corner of a long page, so clicking the button can bring the page directly back to the top. So we should set the button position to fixed position: position: fixed; And fix its position in the lower right corner of the page.
Realize the style
Let’s first look at the style of the implementation button:
#backToTop { position: fixed; right: 20px; bottom: 10px; width: 42px; height: 42px; background-color: #1088e9; color: #ffffff; border-radius: 4px; font-size: 40px; cursor: pointer; text-align: center; &:before { content: '^'; display: block; font-family: serif, 'Times New Roman', Times; } &:hover:before { font-size: 12px; Content: 'back to top '; line-height: 42px; }}Copy the code
Component structure
Let’s implement the basic component structure:
import React from 'react';
import styles from './index.less';
interface BackToTopBtnProps { }
const BackToTopBtn: React.FC<BackToTopBtnProps> = props => {
return (
<div id={styles.backToTop}></div>
)
};
export default BackToTopBtn;
Copy the code
The control button is hidden
Normally, the Back to Top button is not displayed, only when the page is pulled down to a certain height. So we need to listen for scroll events to display buttons when the page scrolls up a certain distance. Now we write a function that listens for scrolling events and uses the React State Hooks and Effect Hooks to control whether the button is visible or not:
import React, { useEffect, useState } from 'react'; import styles from './index.less'; interface BackToTopBtnProps { } const BackToTopBtn: React.FC<BackToTopBtnProps> = props => {// define the visibleBackTopBtn variable to return explicit const of the top button SetVisibleBackTopBtn] = useState(false) useEffect(() => {// Use addEventListener in React to listen for events document.addEventListener('scroll', handleScroll, true); / / component uninstall to remove event listeners return () = > document. The removeEventListener (' scroll 'handleScroll)}, [visibleBackTopBtn]) function / / scroll event listeners const handleScroll = () = > {const scrollTop = window. The document. The body. The scrollTop / / // scrollTop is the height from the top of the scrollbar // scrollHeight is the height of the entire document // We set when the scrolling distance is greater than 200, If (scrollTop > 200) {setVisibleBackTopBtn(true)} else {setVisibleBackTopBtn(false)}} // Click the button event handler Const backToTopHandle = () => {document.body.scrollTo({left: 0, top: 0, behavior: 'smooth' }) } return ( <> { visibleBackTopBtn && <div id={styles.backToTop} onClick={backToTopHandle}></div> } </> ) }; export default BackToTopBtn;Copy the code
Add throttling to reduce event firing
We know that scrolling a page for just a little bit triggers a page scroll event. Frequent triggering of scrolling events can cause performance problems. We need to reduce rolling events to avoid performance issues. So, let’s implement a throttling function:
/** * throttle * @param {*} time time to throttle */ export const throttle = (fn, time) => { let timer = null return (... Args) => {// If timer === false, execute, and rework timer after specified time if(! timer){ fn.apply(this, args) timer = setTimeout(() => { timer = null }, time) } } }Copy the code
Then wrap our scroll event listener with a throttling function:
const handleScroll = throttle(() => {
const scrollTop = window.document.body.scrollTop
if (scrollTop > 200) {
setVisibleBackTopBtn(true)
} else {
setVisibleBackTopBtn(false)
}
}, 500)
Copy the code
As shown in the above code, handleScroll is executed only once at most within 500 milliseconds, which reduces the number of times handleScroll is executed and, to some extent, solves the performance problem caused by the frequent occurrence of scrolling events.
The complete code
index.less
#backToTop { position: fixed; right: 20px; bottom: 10px; width: 42px; height: 42px; background-color: #1088e9; color: #ffffff; border-radius: 4px; font-size: 40px; cursor: pointer; text-align: center; &:before { content: '^'; display: block; font-family: serif, 'Times New Roman', Times; } &:hover:before { font-size: 12px; Content: 'back to top '; line-height: 42px; }}Copy the code
index.tsx
import React, { useEffect, useState } from 'react'; import { throttle } from './utils'; import styles from './index.less'; interface BackToTopBtnProps { } const BackToTopBtn: React.FC<BackToTopBtnProps> = props => { const [visibleBackTopBtn, setVisibleBackTopBtn] = useState(false) useEffect(() => { document.addEventListener('scroll', handleScroll, true) return () => document.removeEventListener('scroll', handleScroll) }, [visibleBackTopBtn]) const handleScroll = throttle(() => { const scrollTop = window.document.body.scrollTop // If (scrollTop > 200) {setVisibleBackTopBtn(true)} else { setVisibleBackTopBtn(false) } }, 500) const backToTopHandle = () => { document.body.scrollTo( { left: 0, top: 0, behavior: 'smooth' } ) } return ( <> { visibleBackTopBtn && <div id={styles.backToTop} onClick={backToTopHandle}></div> } </> ) }; export default BackToTopBtn;Copy the code
utils.ts
/** * throttle * @param {*} time time to throttle */ export const throttle = (fn: Function, time: number): void => { let timer = null return (... Args) => {// If timer === false, execute, and rework timer after specified time if(! timer){ fn.apply(this, args) timer = setTimeout(() => { timer = null }, time) } } }Copy the code
The last eggs
Add the scroll-behavior: smooth to the HTML root element in the CSS; Property that allows smooth scrolling of the page (not supported on older browsers).
html {
scroll-behavior: smooth;
}
Copy the code
In the implementation of the Back to Top button, instead of adding the ScrollBehavior property to the HTML root element, we add the behavior property to the scrollTo parameter to achieve the same effect.
Window.scrollTo()
grammar
window.scrollTo(x-coord, y-coord)
window.scrollTo(options)
parameter
x-coord
Is the horizontal coordinate in the document.y-coord
Is the vertical coordinate in the document.options
Is an object with three attributes:
-
`
top
Is equivalent to
y-coord
`
-
Left is the same thing as x
-coord
`
-
Behavior Type String, indicating rolling behavior. Parameters smooth and instant are supported. The default value auto is used
example
window.scrollTo( 0, 1000 ); // Set the scrolling behavior to window.scrollto ({top: 1000, behavior: "smooth"});Copy the code