摘要:前面既然說到了會把文件夾下面的所有文件編譯成路由,那么子路由需要使用文件夾嵌套才行??蛻舳耸状卧L問的頁面會在服務端做輸出,一旦渲染完成之后,則不會再在服務端輸出,則會一直在客戶端進行輸出了。
服務端預渲染之Nuxt - 使用
現在大多數開發都是基于Vue或者React開發的,能夠達到快速開發的效果,也有一些不足的地方,Nuxt能夠在服務端做出渲染,然后讓搜索引擎在爬取數據的時候能夠讀到當前頁面。
首先要說明一點,我們可以認為我們所編寫的Vue項目是一個服務端的項目,雖然編寫的還是Vue項目,但是Nuxt是基于服務器環境的。
就簡單的說一下Nuxt使用。基礎只是還是以官方文檔為主,如果博客中哪里有問題,歡迎留言指正。
說了這么多,進入正題。
路由
與傳統的Vue項目不同的是,我們在使用Vue的時候需要配置Vue-Router信息,在Nuxt有很關鍵的一點就是約定優于配置。page目錄下的所有*.vue文件會自動生成路由配置。
在項目初始化之后,在pages下面默認有一個index.vue文件,所以當我們使用npm run dev啟動項目,并且使用http://localhost:3000/訪問的時候能夠正常訪問路由。
為了證實上面這一點,在pages下面創建一個信息about.vue文件,并且http://localhost:3000/about去訪問剛剛寫的頁面。我們可以按照正常的Vue頁面去開發就好了。
page目錄
├─page │ ├─index.vue └───└─about.vue
about.vue
This About
創建完成之后使用http://localhost:3000/about訪問該頁面,頁面能夠正常的渲染出來了。就會看到This About顯示在頁面中。
做到這一步之后就應該實現路由之間的跳轉了。Vue開發過程中,都是使用router-link標簽完成路由之間的跳轉,在Nuxt也同樣可以使用router-link,但是Nuxt仍然推薦使用nuxt-link,nuxt-link與router-link的功能是等效的。
可能會有一些疑問,既然是等效的,為什么要使用nuxt-link呢?官方文檔中是這樣說的:將來我們會為nuxt-link組件增加更多的功能特性,例如資源預加載,用于提升nuxt.js應用的響應速度。顯然嘛,官方不會無緣無故的就做出這么一個東西來,肯定實在其中做了很多的優化工作的。
稍微的改動一下剛才的about.vue在里面添加兩個標簽,一個使用nuxt-link,一個使用router-link看下能否正常完成跳轉。
about.vue - 更改后
This About
首頁 首頁
既然從路由開始那么就不得不說到子路由,全局路由守衛這些都些在路由中經常用到的應該怎么處理?該怎么解決這些問題。
前面既然說到了Nuxt會把pages文件夾下面的所有*.vue文件編譯成路由,那么子路由需要使用文件夾嵌套才行。
接下來就嘗試一下。首先要更改一下pgeas目錄結構。
page目錄
├─page │ ├─about │ │ ├─detail.vue │ │ └─index.vue └───└─index.vue
注意上面的about目錄,是index.vue而并非about.vue,這里的index.vue指的是about路由下的首頁,也就是最開始放在與index.vue同級的那個about.vue是一樣的效果。
about/index.vue
This About
首頁 首頁
about/detail.vue
This Detail
現在如果我們想要訪問剛才的那兩個路由地址分別就是http://localhost:3000/about和http://localhost:3000/about/detail就能看到剛才編寫的page頁面了。
如果想要看路由生成到底是什么樣子的?可以在根目錄下有一個.nuxt文件夾,在里面可以看到一個router.js,這個文件夾下面就是Nuex生成好的路由信息。
打開文件后翻到最后會有一段這樣的代碼,是不是很眼熟?這是不就是在編寫Vue項目的時候配置的哪些路由文件么?
router.js
export function createRouter() { return new Router({ mode: "history", base: decodeURI("/"), linkActiveClass: "nuxt-link-active", linkExactActiveClass: "nuxt-link-exact-active", scrollBehavior, routes: [{ path: "/about", component: _9ceb4424, name: "about" }, { path: "/about/detail", component: _18146f65, name: "about-detail" }, { path: "/", component: _d3bf5a4e, name: "index" }], fallback: false }) }
有了這個文件的話我們就可以清楚的知道,路由的結構了。不僅僅這樣,還可以使用name去實現路由的跳轉了。
需要注意的是,如果你的路由是有文件夾嵌套的話,Nuxt是用使用-來拼接路由的name名稱的(如:about-detail),但是文件夾內部的index.vue會直接已文件夾的名字作為name。一旦知道了路由的name,這樣我們就可以使用命令的方式跳轉路由了。
再次更改一下about/index.vue。
about/index.vue
This About
詳情 首頁
使用路由訪問http://localhost:3000/about地址,分別點擊詳情、首頁與button,都是能夠正常跳轉的,與之前的Vue開發是完全沒有任何區別的。在vue-router中有一個很重要的一個點就是動態路由的概念,如果想要實現動態路由應該怎么處理呢?
如果想要在Nuxt中使用動態路由的話,需要在對應的路由下面添加一個_參數名.vue的文件,在about文件下面添加一個_id.vue
page目錄
├─page │ ├─about │ │ ├─detail.vue │ │ ├─_id.vue │ │ └─index.vue └───└─index.vue
新建完成之后在去router.js中看一下更改后的路由結構
export function createRouter() { return new Router({ mode: "history", base: decodeURI("/"), linkActiveClass: "nuxt-link-active", linkExactActiveClass: "nuxt-link-exact-active", scrollBehavior, routes: [{ path: "/about", component: _9ceb4424, name: "about" }, { path: "/about/detail", component: _18146f65, name: "about-detail" }, { path: "/about/:id", component: _6b59f854, name: "about-id" }, { path: "/", component: _d3bf5a4e, name: "index" }], fallback: false }) }
可以明顯的看到在/about/:id這個路由,明顯的變化不止這些變動的還有name: "about-id"不再是之前的name:about了。如果想要使用這個id的話必須在_id.vue中才能獲取到。
_id.vue
{{$route.params.name}} {{$route.params.id}}
在_id.vue中編寫以上代碼并使用http://localhost:3000/about/ABC,可以看到在頁面中已經展示了當前的id值。
在實際開發過程當中可能params可能會有多個參數,又應該怎么處理呢?
調整目錄結構
// id為可選參數 ├─page │ ├─about │ │ ├─_name | | | └─_id | | | └─index.vue │ │ └─index.vue └───└─index.vue
about - _name - _id.vue
{{$route.params.name}} {{$route.params.id}}
弄完之后看下router.js的變化
export function createRouter() { return new Router({ mode: "history", base: decodeURI("/"), linkActiveClass: "nuxt-link-active", linkExactActiveClass: "nuxt-link-exact-active", scrollBehavior, routes: [{ path: "/about", component: _9ceb4424, name: "about" }, { path: "/about/detail", component: _18146f65, name: "about-detail" }, { path: "/about/:name", component: _2ec9f53c, name: "about-name" }, { path: "/about/:name/:id", component: _318c16a4, name: "about-name-id" }, { path: "/", component: _d3bf5a4e, name: "index" }], fallback: false }) }
這里展示的是第二種情況,id為必選參數的情況,路由被編譯的結果。
雖然路由已經添加了參數,但是id屬性不是必填屬性,這樣的話不能滿足項目需求又要如何處理呢?很簡單的,在_id.vue文件同目錄下添加一個index.vue文件就可以了。
// id為必選參數 ├─page │ ├─about │ │ ├─_name | | | ├─_id.vue | | | └─index.vue │ │ └─index.vue └───└─index.vue
需要注意的是,一定要在_id.vue文件中使用傳入的參數,直接獲取在index.vue中是拿不到任何信息的。但是如果訪問http://localhost:3000/about/ABC這樣的路由的話,實在index.vue中是可以獲取到name參數的。
在剛才的router.js文件中生成的所有的路由都是平級的,如何實現路由的嵌套,如果想要實現嵌套路由的話,必須有和當前路由同名的文件夾存在,才能完成路由的嵌套。
page目錄
├─page │ ├─about | | ├─_id.vue | | └─detaile.vue │ ├─about.vue └───└─index.vue
router.js
export function createRouter() { return new Router({ mode: "history", base: decodeURI("/"), linkActiveClass: "nuxt-link-active", linkExactActiveClass: "nuxt-link-exact-active", scrollBehavior, routes: [{ path: "/about", component: _76687814, children: [{ path: "", component: _9ceb4424, name: "about" }, { path: ":id", component: _6b59f854, name: "about-id" }] }, { path: "/", component: _d3bf5a4e, name: "index" }], fallback: false }) }
更改完目錄結構,那我們嵌套的路由應該如何展示?在vue.js中開發的時候使用router-view這個標簽完成的。為了性能的優化Nuxt也提供了一個對應的標簽nuxt-child。
如果想實現嵌套路由傳參需要稍微的改動一下目錄結構,按照上面的方法實現就好了,下面是一個路由結構的例子。
page目錄
├─page │ ├─about │ │ ├─detail | | | ├─_id.vue | | | └─index.vue │ │ └─index.vue └───└─index.vue
router.js
export function createRouter() { return new Router({ mode: "history", base: decodeURI("/"), linkActiveClass: "nuxt-link-active", linkExactActiveClass: "nuxt-link-exact-active", scrollBehavior, routes: [{ path: "/about", component: _76687814, name: "about", children: [{ path: "detail", component: _0a09b97d, name: "about-detail" }, { path: "detail/:id?", component: _fa7c11b6, name: "about-detail-id" }] }, { path: "/", component: _d3bf5a4e, name: "index" }], fallback: false }) }
在_id.vue中則可以使用id這個參數了。訪問路由http://localhost:3000/about/detail/123,依然可以拿到傳入的id為123的這個參數。
說了這么多了,還有很多問題沒得說完,關于路由的全局守衛又應該如何去使用?在Nuxt根目錄下有個plugins文件夾。首先要做的是在里面創建一個名為router.js文件。
plugins-router.js
export default ({app}) => { app.router.beforeEach((to,form,next) => { console.log(to) next(); }); }
導出了一個函數,在這個函數中可以通過結構拿到vue的實例對象名叫app。需要注意的是,這個beforeEach函數的執行,有可能會在服務端也會有可能在客戶端輸出??蛻舳耸状卧L問的頁面會在服務端做輸出,一旦渲染完成之后,則不會再在服務端輸出,則會一直在客戶端進行輸出了。
說到這里做個小插曲,那么又該怎么區分當前是在客戶端環境還是服務端環境呢?可以使用process.server獲取到當前的運行環境,其得到的是Boolean值,true服務端,fasle客戶端。
做了這些之后去訪問路由,仿佛沒有任何輸出,無論實在客戶端還是在服務端,都沒有任何打印輸出,中間缺少了步驟,需要在根目錄下找到nuxt.config.js對插件進行配置。
nuxt.config.js
const pkg = require("./package") module.exports = { plugins: [ "@/plugins/element-ui", "@/plugins/router" ] }
由于更改了Nuxt配置需要重啟一下服務,才能正常執行剛剛寫入的插件。然后訪問剛剛寫入的路由,會看在服務端初次渲染的時候,會輸出我們想要的那些東西,進行路由跳轉的話,會在客戶端輸出,這也就證明了Nuxt只會做首屏的服務器渲染。
路由說了這么接下來需要說一下Nuxt是如何為指定的路由配置數據做渲染的。其實Nuxt在做渲染的時候包裹了很多層。首先有一個Document作為其模板,然后再去尋找其布局的頁面,找到對應的頁面之后,再根據引用去找到相關的組件進行渲染,數據請求與數據掛載,一系列完成之后,把剩余的路由信息返還給客戶端,渲染完成,這個就是Nuxt簡單的渲染流程。
在上面提到了一個布局頁面,這個東西應該去哪里找?又應該怎么做呢?它對于項目而言對于開發又有什么好處?在Nuxt根目錄下有一個layouts文件夾,下面有一個default.vue這個文件就是上面提到的渲染頁面,也就同等于vue開發中的App.vue,在這里可以做很多事情。例如添加一個全局的導航。
在layouts文件夾添加一個about.vue文件寫入如下內容,接下來需要在pages下面的about.vue中通知,對應pages使用哪個布局頁面,不寫則使用默認,然后訪問http://localhost:3000/about相關的頁面,只要是和about相關的頁面,都會展示這個內容。
layouts - about.vue
Aaron 個人博客主頁
pages - about.vue
About
訪問一下所有與about頁面有關的頁面,都會看到Aaron個人博客主頁這個字樣,若訪問根路由則無法看到的。
如果做過mvc開發的話,如果頁面發生錯誤會跳轉到一個錯誤頁面的。Nuxt也是有默認的錯誤頁面的,但是全是英文而且樣式也不太好看,不能自定義樣式。如何自定義錯誤頁面呢?
在layouts文件夾中新建一個error.vue文件。
layouts - error.vue
這里是錯誤頁面
404 - 頁面不存在
500 - 服務器錯誤
HOME
在error.vue中可以通過props拿到一個error對象,獲取到error錯誤信息之后能做任何想要做的事情。需要注意的一點是,自定意的錯誤頁面,只能在客戶端訪問失效的時候才會響應到該頁面,若在服務端的話,是無法直接渲染這個頁面的。
更改頁面配置Nuxt中有些全局的配置,配置信息在nuxt.config.js更改其全局配置,pages文件夾中的*.vue文件也是可以配置的,頁面私有的配置會覆蓋掉全局的配置。
舉例:
export default { layout:"about", head: { title:"About" } }
在這些全局配置中最重要的一個就是asyncData這個屬性。asyncData到底是用來做什么的呢?這個數據可以在設置組件的數據之前能一步獲取或者處理數據。也就是說在組件渲染之前先獲取到數據,然后等待掛載渲染。
舉個例子:
姓名:{{userInfo.name}}
年齡:{{userInfo.age}}
一定要return出去獲取到的對象,這樣就可以在組件中使用,這里返回的數據會和組件中的data合并。這個函數不光在服務端會執行,在客戶端同樣也會執行。
注意事項:
asyncData 方法會在組件(限于頁面組件)每次加載之前被調用
asyncData 可以在服務端或路由更新之前被調用
第一個參數被設定為當前頁面的上下文對象
Nuxt會將 asyncData 返回的數據融合到組件的data方法返回的數據一并返回給組件使用
對于 asyncData 方式實在組件初始化前被調用的,所以在方法內飾沒辦法通過this來引用組件的實例對象
剛剛提到了一點就是上下問對象,在上線文對象中可以獲取到很多東西,如路由參數,錯誤信息等等等,這里就不作太多贅述了,有了這些可以做一些頁面的重定向或者其他工作,比如參數校驗,安全驗證等工作。
路由扯了一大堆,接下來說一下如何在Nuxt中融入axios的使用。
安裝axios
npm install @nuxtjs/axios --save-dev
安裝完成后更改配置信息:
nuxt.config.js
module.exports = { modules: [ // Doc: https://axios.nuxtjs.org/usage "@nuxtjs/axios", ], axios: { proxy:true // 代理 }, proxy: { "/api/":"http://localhost:3001/" // key(路由前綴):value(代理地址) } }
主要說名一下proxy這里,/api/在請求的時候遇到此前綴則會只指向的代理地址去請求數據。
既然說到了axios,就不得不提到的一個東西就是攔截器,很是有用在項目開發過程中必不可少的。
舉個例子:
module.expores{ plugins: [ "@/plugins/axios" ], modules: [ // Doc: https://axios.nuxtjs.org/usage "@nuxtjs/axios", ], }
plugins/axios.js
export default ({ $axios, redirect }) => { $axios.onRequest(config => { console.log("Making request to " + config.url) }) $axios.onError(error => { const code = parseInt(error.response && error.response.status) if (code === 400) { redirect("/400") } }) }
總結
說了這么多也許會有些紕漏,或者遺漏的知識點,若有什么錯誤的地方可以在下方留言,盡快做出改正。謝謝大家花費這么長時間閱讀這篇文章。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/103313.html
摘要:為了解決問題,推出了服務端預渲染,以便提高對優化。應用,到了,單頁面應用優秀的用戶體驗,逐漸成為了主流,頁面整體式渲染出來的,稱之為客戶端渲染??蛻舳私邮諗祿缓笸瓿勺罱K渲染。通過對客戶端服務端基礎框架的抽象組織,主要關注的是應用的渲染。 現在前端開發一般都是前后端分離,mvvm和mvc的開發框架,如Angular、React和Vue等,雖然寫框架能夠使我們快速的完成開發,但是由于前...
摘要:根據官方文檔在文件下面創建兩個文件,分別是和。在中可以直接使用,并且是默認啟用命名空間的。在中觸發熱更新。使用中間件中間件沒有給出具體的使用文檔,而是放入了一個編輯器。對配置有興趣的可以在官方文檔找到渲染文檔。 Nuxt是解決SEO的比較常用的解決方案,隨著Nuxt也有很多坑,每當突破一個小技術點的時候,都有很大的成就感,在這段時間里著實讓我痛并快樂著。在這里根據個人學習情況,所踩過的...
摘要:最近簡單的研究了一下,對已經有了一個簡單的認知,主要應用于單頁面應用,是很不錯的框架。創建好之后,在命令行直接輸入即可,當控制臺顯示服務已啟動則表示該服務已經啟動成功了。配置參數中有一項為這項配置的就是我們即將使用的模板。 最近簡單的研究了一下SSR,對SSR已經有了一個簡單的認知,主要應用于單頁面應用,Nuxt是SSR很不錯的框架。也有過調研,簡單的用了一下,感覺還是很不錯。但是還是...
摘要:感悟經過幾個周六周日的嘗試,終于解決了服務端渲染中的常見問題,當不在是問題的時候,或許才是我們搞前端的真正的春天,其中也遇到了一些小坑,官方還是很給力的,提后很積極的給予幫助,再次感謝的開發團隊。 感悟 經過幾個周六周日的嘗試,終于解決了服務端渲染中的常見問題,當SEO不在是問題的時候,或許才是我們搞前端的真正的春天,其中也遇到了一些小坑,Nuxt.js官方還是很給力的,提issue后...
閱讀 2322·2021-11-08 13:13
閱讀 1253·2021-10-09 09:41
閱讀 1696·2021-09-02 15:40
閱讀 3194·2021-08-17 10:13
閱讀 2553·2019-08-29 16:33
閱讀 3129·2019-08-29 13:17
閱讀 3141·2019-08-29 11:00
閱讀 3303·2019-08-26 13:40