next的Link组件

最近项目中要快速开启站群系统开发,调研了很多的框架:ghost、wordpress、hexo、vuepress、next,发现各个在各自的使用环境中都有优势。ghost虽然可以前后端共用一套、使用node+handlebars的服务端渲染,通过开发不同主题包来更改站点,但是缺点主要是没办法一套共用多个站点。至于其他hexo、hugo、vuepress这些静态页面生成,不支持动态数据配置、每次不同站点使用、都得打包发布,不太灵活。而next主要有ssrssg(最主要是预渲染、其中重点isr-增量静态重新生成页面)、spa,比较适合前期的灵活开发,而且自带了些组件优化ImageLinkScript,都很适合我们当前项目中图片资源相对多的系统,因此本文侧重于Link组件学习

1、Link

是一个 React 组件,它扩展了 HTML<a>元素以提供路由之间的预加载和客户端导航,通俗理解就是使用该组件可以提前加载下一个页面的资源

2、测试效果

// 快速安装使用、
npx create-next-app@latest

分别在新版本app-router和旧版本的pages下测试

image.png

最终会渲染成a标签,对于seo中,是可以被搜索引擎爬取到

相关代码如下

//src/app/page.tsx
import Link from 'next/link'
import styles from './page.module.css'

export default function Home() {
  return (
    <main className={styles.main}>
      <div style={{
        'display': 'flex',
        'flexDirection': 'column',
        'paddingTop': '600px'
      }}>
        <div>
          <Link href="/test">app-router的test页面</Link>
        </div>
        <div>
          <Link href="/dynamic/test">app-router的动态页面</Link>
        </div>
        <div>
          <Link href="/test/a" >pages下的a页面</Link>
        </div>
        <div>
          <Link href="/test/b">pages下的b页面</Link>
        </div></div>
    </main>
  )
}

//src/app/dynamic/[slug]/page.tsx
export default function Page({
    params,
    searchParams,
}: {
    params: { slug: string }
    searchParams: { [key: string]: string | string[] | undefined }
}) {
    return <h1>app-router的动态页面{params.slug}</h1>
}

//src/app/test/page.tsx
"use client"

export default function Test() {
    const handleClick = () => {
        alert(1)
    }

    return (<>
        <div>app-router的test页面  </div>
        <div onClick={handleClick}>点击我</div>
    </>)
}

//src/pages/test/a.tsx
export default function A() {
    return <><div>a-pages页面</div></>
}
//src/pages/test/b.tsx
"use client"
import { GetStaticProps } from 'next'
interface props {
    a: number;
    b: number;
    c: number;
}
export const getStaticProps: GetStaticProps = async () => {
    return {
        props: { a: 1, b: 2, c: 3 },
    }
}
export default function B(props: props) {
    const handleClick = () => {
        alert(1)
    }

    return (<>
        <div>b-pages页面 {props.a}</div>
        <div onClick={handleClick}>点击按钮</div>
    </>)
}

yarn build
yarn start

3、测试效果:

6355c666-fb84-4aa0-9bd9-150ddff7ca46.gif

  • 目前这个预加载需要在生产环境中使用
  • 当前组件Link具有类似图片懒加载效果,当其链接出现在可视窗口后,会加载对应页面的资源,只是两个路由的处理方式有点区别
  • 针对于app-router测试效果:
    • 会提前加载两个页面的数据和js代码,然后通过客户端渲染,直接在当前页面运行
    • 进入两个页面后,不会再加载对应页面的资源
    • 重新刷新页面,就会加载当前页面所有资源
    • next.js 会使用浏览器的原生导航能力,通过使用 pushState API 在不刷新整个页面的情况下更改 URL,并将页面组件加载到页面中。这样可以提供快速、无缝的页面切换体验,同时保持页面状态和用户输入的持久性

image.png

image.png

  • 针对pages路由测试效果:
    • 发现两个页面加载是对应页面的文档
    • 点击跳转到对应页面,发现这时候用的是浏览器的304协商缓存
    • 重新刷新页面,仍然使用304重定向 image.png

4、应用

后面也会把这种技巧用到微游中心,异步提前加载下个页面资源,然后使用客户端渲染或者配合使用浏览器的协商缓存方式来预加载页面资源

5、源码里主要方法

通过监听链接组件的 onTouchStart、onMouseEnter的事件,可以提前预加载资源
prefetch方法:主要是用来浏览器空闲时,预先加载资源
linkClicked方法:主要是通过preventDefault来取消默认事件,然后重新定义用来跳转对应页面方式

6、参考

猜你喜欢

转载自juejin.im/post/7253442601855598649