没事造轮子没事造轮子

没事造轮子

网站加载动画实现

  • W_Z_C
  • 阅读约 2 分钟
网站加载动画实现

本篇文章主要介绍如何在现有的网站上添加加载动画。加载动画对于网站来说并不是必须的,但是因为 Nextjs 在网页切换的时候会在后台动态加载页面数据,如果页面数据量较大,或者网络条件糟糕的情况下,会让用户感觉点击没有生效,根本原因是在加载的过程中没有一个明确的反馈信息,今天介绍的加载动画就是为了缓解这个问题。

想要实现加载动画效果,需要借助 Nextjs 的路由系统。在路由系统上你可以监听一系列的事件:

  • routeChangeStart(url, { shallow }),当路由开始改变的时候触发。
  • routeChangeComplete(url, { shallow }),当路由完成改变的时候触发。
  • routeChangeError(err, url, { shallow }),当路由加载失败的时候触发。

目前主要监听了上面的三个路由事件。在路由开始改变的时候,显示加载动画,当完成或者发生错误的时候隐藏动画。

1. 动画加载组件

实现加载动画首先要创建一个前端组件,用它来承载动画内容:

Loading.js
import { Transition } from '@headlessui/react'
import { Fragment } from 'react'

export default function Loading({ loading }) {
    return (
        <Transition
            show={loading}
            as={Fragment}
            enter="transition ease-in-out duration-300 transform"
            enterFrom="-translate-y-full"
            enterTo="translate-y-0"
            leave="transition ease-in-out duration-300 transform"
            leaveFrom="translate-y-0"
            leaveTo="-translate-y-full"
        >
            <div className="w-screen h-screen absolute z-50 bg-white">
                <div className="absolute left-0 right-0 top-0 bottom-0 m-auto text-center h-12 md:h-14">
                    <img src="/assert/images/logo.png" className="m-auto h-12 md:h-14 transition-transform animate-spin" alt="Loading..." />
                    <div className="pt-2 animate-pulse">Loading...</div>
                </div>
            </div>
        </Transition>
    )
}

代码很简单就是单纯的显示了一个 logo,并弄了个旋转动画效果。

2. 监听路由事件

接下来就是前面提到的监听路由事件:

_app.js
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import '../styles/globals.css'

function MyApp({ Component, pageProps }) {
  const router = useRouter()
  const [loading, setLoading] = useState(false)

  useEffect(() => {
		const handleChangeStart = (url) => {
			setLoading(true)
		}

		const handleChangeComplete = (url) => {
			setLoading(false)
		}

		router.events.on('routeChangeStart', handleChangeStart)
		router.events.on('routeChangeComplete', handleChangeComplete)
		router.events.on('routeChangeError', handleChangeComplete)

		return function cleanup() {
			router.events.off('routeChangeStart', handleChangeStart)
			router.events.off('routeChangeComplete', handleChangeComplete)
			router.events.off('routeChangeError', handleChangeComplete)
		}
	}, [router])

  return <Component {...pageProps} />
}

组件中创建了一个 loading 状态,当路由开始切换的时候,则设置该状态值为 true,当完成的时候将其重置为 false,在以后的代码中,可以根据该状态的值来判断网站是否处于加载状态。

3. 显示加载组件

接着修改原来的函数返回值,将 Loading 组件添加进去,并且设置加载状态下隐藏主界面。

_app.js
function MyApp({ Component, pageProps }) {
  
  //...
  
  return (
    <>
      <Loading loading={loading} />
      <main className={loading ? "hidden" : "block"}>
        <Component {...{ ...pageProps, loading }} />
      </main>
    </>
  )
}

加载动画的实现还是很简单的,不过注意一下最后的代码,我们将 loading 状态传入了子组件 Component 的内部,这是因为在显示页面的过程中,可能会用到这个状态值,所以特意添加进去。