如果你熟悉 react-router
,你一定喜欢它提供单页路由。NextJs
也支持这一功能。
代码
这里,我们先定义一个 Nav.js
的组件,用于多个页面的公共导航部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import React from 'react'; import Link from 'next/link';
const InactiveLink = ({ path, name }) => ( <li> <Link href={path}> <a><strong>{name}</strong></a> </Link> </li> ); const ActiveLink = ({ name }) => ( <li> {name} </li> );
const Nav = ({ location }) => { const navs = [ { path: 'home', name: '首页' }, { path: 'other', name: '其他' }, { path: 'about', name: '关于' } ]; return ( <ul> { navs.map((nav) => { if (nav.path === location) { return <ActiveLink key={nav.path} name={nav.name} /> } return <InactiveLink key={nav.path} path={`./${nav.path}`} name={nav.name} /> }) } </ul> ); };
export default Nav;
|
然后在 pages/route/
下新建 home.js
, other.js
, about.js
三个文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import React from 'react'; import Nav from '../../components/route/nav'; export default () => ( <div> <Nav location="home" /> <p>这是首页</p> </div> );
import React from 'react'; import Nav from '../../components/route/nav'; export default = () => ( <div> <Nav location="other" /> <p>其他内容</p> </div> );
import React from 'react'; import Nav from '../../components/route/nav';
export default () => ( <div> <Nav location="about" /> <p>关于我们</p> </div> );
|
npm run dev
启动项目,点击不同的链接,页面不刷新,但是会动态的切换内容。
说明
上面的代码中,唯一陌生的部分应该就是 <Link>
了。检查元素,发现 Link
被解析到了 a 标签上。当然,a 标签并不是必须的。
这里还有一个担心就是,单个页面包含太多文件,导致页面加载缓慢。开发者工具观察网络,发现页面所用到的文件是动态加载的,所以这个担心是不必要的。
如果子页面过大,路由切换的时候还是会导致较长时间的等待,影响用户体验。NextJs
的 Link
提供 prefetch
属性,可以预加载子页面。修改 nav.js
代码如下:
1 2 3 4 5 6 7 8 9
| const InactiveLink = ({ path, name }) => ( <li> <Link prefetch href={path}> <a><strong>{name}</strong></a> </Link> </li> ); // ...
|
prefetch
是一个生成专用的功能,需要注意的是:通过 prefetch
Next.js
只下载 JS 代码。当页面呈现时,您可能需要等待数据。除了使用 Link
,也可以通过 Router.prefetch('/dynamic')
这样的高级用法实现。
有的时候,Link
不方便使用,也可以使用 Router.push()
代替。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import Router from 'next/router'
const handler = () => Router.push({ pathname: '/about', query: { name: 'Zeit' } })
export default () => ( <div> Click <span onClick={handler}>here</span> to read more </div> );
|
Router
还提供了一系列路由变化周期中的钩子函数,这里不作重点说明:
onRouteChangeStart(url)
- 当路由开始改变时触发
onRouteChangeComplete(url)
- 当路由完全改变时触发
onRouteChangeError(err, url)
- 更换路由时发生错误时触发
onBeforeHistoryChange(url)
- 在更改浏览器的历史记录之前触发
onAppUpdated(nextRoute)
- 切换页面时触发,并有一个新版本的应用程序