路由到另外一个页面_Nextjs使用解读一(项目搭建与路由系统)
1. 之前想搭建個(gè)人博客,由于學(xué)習(xí)的是react技術(shù)棧,所以就到處搜羅資料學(xué)了nextjs,配合koa就把博客搭起來了。該系列文章基于我的學(xué)習(xí)筆記,重新整理了一遍,如果有錯(cuò)誤之處,還請指正。
2. 個(gè)人能力有限,我更注重的是使用,所以對于許多原理也只是簡單理解,并未深究。如果是想研究源碼,或者追求性能深度優(yōu)化的老鐵,可以不用往下看了
3. 轉(zhuǎn)載請注明出處
各工具版本:npm v6.10,node v12.13,react v16.12,next v9.1
可能需要的預(yù)備知識:React項(xiàng)目經(jīng)驗(yàn)、nodejs開發(fā)經(jīng)驗(yàn),webpack、npm等常用工具使用經(jīng)驗(yàn)。最好會koa(部分地方可能會用到)
一、Nextjs與服務(wù)端渲染
Nextjs的官方解釋:Next.js 是一個(gè)輕量級的 React 服務(wù)端渲染應(yīng)用框架。
服務(wù)端渲染,顧名思義,就是在服務(wù)器上就把網(wǎng)頁渲染好了,你請求時(shí),直接發(fā)給你渲染好的頁面。知道了原理,ssr的優(yōu)勢劣勢也就很明顯了:
與客戶端渲染比較
優(yōu)勢:
1. 更利于SEO,便于搜索引擎收錄。因?yàn)榇蠖鄶?shù)爬蟲只會爬源碼,不會爬腳本,當(dāng)服務(wù)端返回渲染好的數(shù)據(jù)后爬蟲便能直接爬取了。
2. 利于首屏加載。這個(gè)簡單,服務(wù)端發(fā)過來的就是渲染好的,客戶端就省事了,加載也就快了。
劣勢就是:1. 服務(wù)器的壓力大了(多了活要干);2. 對開發(fā)人員要求也高了
(深有體會,量發(fā)而行!這已經(jīng)不屬純正血統(tǒng)的前端范疇了,因?yàn)橐晒Σ渴鸬脑?#xff0c;你還不得不心甘情愿地去學(xué)點(diǎn)服務(wù)器知識、Linux運(yùn)維、nginx部署等)
特別注意
二、搭建Nextjs項(xiàng)目
實(shí)踐出真知。介紹完了,作為正經(jīng)的程序員,先上手一個(gè)再慢慢研究。我們按照官網(wǎng)的節(jié)奏,一步步搭建項(xiàng)目,再一步步解釋每個(gè)文件和目錄的作用
1. 搭建環(huán)境
說明:和react項(xiàng)目類似,這里的命令build即部署時(shí)的打包命令,start運(yùn)行打包后的文件命令,dev則是開發(fā)環(huán)境下啟動nextjs服務(wù)器。
到這里,環(huán)境就算搭建好了。
2. 創(chuàng)建pages目錄
Nextjs的路由系統(tǒng)非常簡單,所有的路由頁面全部存放在pages目錄下,nextjs會自動對應(yīng)page目錄的文件路徑生成對應(yīng)路由。
如,我們在pages創(chuàng)建demo.js:
export default () => <div>This is the demo page</div>然后啟動next服務(wù)器:npm run dev
命令行顯示如下時(shí)表示啟動成功了
此時(shí)打開瀏覽器,進(jìn)入localhost:3000/demo,便能看到頁面了
路由/demo顯示界面3._app.js和 _document.js
特別的,pages下有兩個(gè)特殊文件:_app.js和_document.js。這兩個(gè)文件默認(rèn)是隱藏的,新建的話就會覆蓋之前的文件。他們分別用來自定義APP和自定義Document
自定義?什么意思?有什么用?簡單來說就是用來定義一些頁面共用的屬性(如設(shè)置全局css,通用布局等),或者定義一些通用的動作(如獲取、傳遞數(shù)據(jù)等), 這個(gè)結(jié)合nextjs的getInitialProps函數(shù)會更好說明,就留著后續(xù)講getInitialProps數(shù)據(jù)獲取和頁面布局的時(shí)候再一并解釋吧。
這篇文章我們主要關(guān)注路由系統(tǒng)。
三、路由系統(tǒng)
保證pages目錄的干凈
對于現(xiàn)在的組件化開發(fā),我們通常會有兩種組件,一種作為某個(gè)獨(dú)立功能的小組件,一種是作為頁面顯示的頁面組件(通常結(jié)合了多個(gè)小組件),Nexjs同樣適用, 但小組件不能存儲在pages目錄下,這會導(dǎo)致路由系統(tǒng)混亂。我們可以新建一個(gè)components目錄(根據(jù)自己喜好自定義名字)來存儲小組件,在需要時(shí)從該目錄下import使用即可。
多級路由:
如果路由有多級,直接在pages下創(chuàng)立父級目錄,再把最終路由文件放入目錄下即可實(shí)現(xiàn)多級路由。如在pages目錄下創(chuàng)建user目錄,user下再創(chuàng)建index.js和home.js,那么路由/user就對應(yīng)index.js文件,/user/home就對應(yīng)home.js文件
路由跳轉(zhuǎn)
Nextjs官方推薦了兩種跳轉(zhuǎn)方式,一種是Link組件包裹,一種使用Router,我個(gè)人是不推薦Link的,原理也是用Router實(shí)現(xiàn)的,使用也簡單,但用起來總感覺很冗余。我這里主要介紹Router,想了解Link的老鐵得麻煩移步官網(wǎng)了。
Nextjs提供了一個(gè)'next/router'的包,專門用來處理路由。Router便是其中一個(gè)對象,Router.push('url')進(jìn)行跳轉(zhuǎn)。
實(shí)踐一下:
1. pages目錄下,創(chuàng)建index.js文件
2. 修改demo.js文件
import React from 'react' import Router from 'next/router'export default () => {return(<><button onClick={()=>Router.push('/')} >送我去主頁</button><div>這里是demo頁</div></>) }3. 運(yùn)行結(jié)果
點(diǎn)擊“送我去demo頁”按鈕后
路由參數(shù)
注意!注意!Nextjs不能使用params傳參數(shù)!只能通過query!
像這樣
Router.push('url?id=1') 等價(jià) Router.push({pathname:'url',query:{id:1}})另外,前面說過,服務(wù)端渲染時(shí)沒有window對象的,自然不能通過傳統(tǒng)途徑獲取url參數(shù),這里'next/router'里提供了一個(gè)withRouter對象,用它包裹組件后,組件會多出router的參數(shù),通過router就能獲取query參數(shù)了
import React from 'react' import Router,{ withRouter } from 'next/router'const Demo = (props) => {return(<><button onClick={()=>Router.push('/')} >送我去主頁</button><div>這里是demo頁</div><div>{props.router.query.id}</div></>) } export default withRouter(Demo);成功顯示id的值:1路由映射
我們常看到的url是這樣的/url?id=1,而路由映射可以幫我們顯示成為這樣 /url/1,比較美觀友好(其實(shí)也就好一點(diǎn)點(diǎn)),這小節(jié)講解下路由映射,會涉及到koa使用,不感興趣的小伙伴直接跳過吧,畢竟也不是什么特別重要的
"表面上"的實(shí)現(xiàn)方法:
1. Router.push({ pathname: '/demo', query: { id: 1 } },'/demo/1')Router.push的第三個(gè)參數(shù)即可指定別名 2. Link組件中的as屬性<Link href='/demo?id=1' as='/demo/1'>這樣看上去的確可以了,初始時(shí)也能訪問,但頁面一刷新就會404,為什么?因?yàn)楫?dāng)我們點(diǎn)擊按鈕在瀏覽器端跳轉(zhuǎn)時(shí),是瀏覽器去找頁面,它通過路由映射可以找到。而刷新的時(shí)候,是服務(wù)器去找,而我們的pages頁面里面沒有/demo/1的文件,所以就報(bào)404了。
解決辦法,利用koa處理:
router.get('/demo/:id',async (ctx)=>{cosnt id = ctx.params.id await handle(ctx.req,ctx.res,{pathname:'/demo',query: {id}}),ctx.respond = false })其實(shí)就是在服務(wù)器處又將路由轉(zhuǎn)換回來而已。
路由鉤子
Router中還定義了幾個(gè)鉤子函數(shù)用來獲取路由轉(zhuǎn)變時(shí)的狀態(tài),方便我們在轉(zhuǎn)換路由時(shí)進(jìn)行操作
// routeChangeStart history模式路由改變剛開始 // routeChangeComplete history模式路由改變結(jié)束 // routeChangeError 路由改變失敗 // hashChangeStart hash模式路由改變剛開始 // hashChangeComplete hash模式路由改變結(jié)束Router.events.on(event,func()) //event即監(jiān)聽的事件(以上5種),func回調(diào)函數(shù) Router.events.off(event,func()) //取消監(jiān)聽好了,路由系統(tǒng)就講解到這了,下一篇文章會講解到nextjs的布局和getInitialProps()函數(shù),順帶會把這期遺留的_app.js和_document.js一并解釋了。
喜歡的話歡迎分享,歡迎討論
歡迎關(guān)注我的其他平臺賬號: 【知乎】均遠(yuǎn) 【公眾號】佛系前端 【個(gè)人博客】http://xujunyuan.com 【GitHub】JunYuanHub
總結(jié)
以上是生活随笔為你收集整理的路由到另外一个页面_Nextjs使用解读一(项目搭建与路由系统)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 第三方模块之 psutil
- 下一篇: 《操作系统》OS学习(十):进程控制