您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關使用Nuxt.js怎么實現一個SSR前端博客,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
目錄結構
assets: 資源文件。用于組織未編譯的靜態資源如 LESS、SASS或 JavaScript。
components: 組件。
layouts: page: 模板頁面,默認為 default.vue可以在這個目錄下創建全局頁面的統一布局,或是錯誤處理頁面頁,需要提供一個nuxt 標簽,類似于router-view
middleware: 中間件,放置自定義的中間件,會在加載組件之前調用。可以在頁面中調用: middleware: '中間件名稱'。
pages: 頁面,index.vue 為根頁面,Nuxt.js 框架讀取該目錄下所有的 .vue文件并自動生成對應的路由配置,如需要動態參數id,則可以添加_id的文件,必須是下劃線加參數名。
plugin: 插件,用于組織那些需要在 根Vue.js應用實例化之前需要運行的 Javascript 插件。
static: 靜態文件,靜態文件目錄 static用于存放應用的靜態文件,此類文件不會被 Nuxt.js 調用 Webpack 進行構建編譯處理。
store: 用于組織vuex狀態管理。具體使用請移步至 官網。
nuxt.config.js: nuxt.config.js文件用于組織Nuxt.js 應用的個性化配置,配置head,loading,css,plugins等。
Nuxt.js生命周期
1. incoming Request 瀏覽器發出的請求)
2. nuxtServerInit 服務端接受請求后,要檢查當前有沒有 nuxtServerInit配置項,如果有就執行這個函數
3. store action 用來操作vuex
4. middleware 可以做jWT等一些操作。
5. validate() 檢驗參數,參數檢驗失敗,可以在layout里的error里面進行捕捉。
6. asyncData()& fetch() asyncData用來渲染組件,fetch用來渲染vuex
7. Render
Nuxt擴展以后的生命周期和方法以下:
beforeCreate: ? beforeCreate() components: {NuxtLoading: {…}} computed: {isOffline: ?} context: {isStatic: false, isDev: true, isHMR: true, app: {…}, payload: undefined, …} created: ? created() data: ? data() head: {title: "nuxt-meituan-ssr", meta: Array(3), link: Array(1), style: Array(0), script: Array(0)} methods: {refreshOnlineStatus: ?, refresh: ?, errorChanged: ?, setLayout: ?, loadLayout: ?} mounted: ? mounted() nuxt: {…} render: ? render(h, props) router: VueRouter {app: Vue, apps: Array(1), options: {…}, beforeHooks: Array(2), resolveHooks: Array(0), …} watch: {nuxt.err: "errorChanged"}
注意:
Vue.js生命周期的鉤子只有beforeCreate和created會在服務端和客戶端渲染。
以上生命周期里都獲取不到window對象。
asyncData和fetch我們可以拿到數據,不要嘗試掛載數據到data上,此時獲取不到this對象。
開發總結
如何修改默認啟動端口?
可以在package.json下面修改配置,如下。
"config":{ "nuxt":{ "host":"127.0.0.1", "port":"3304" } }
如何添加全局的樣式?
可以在assets里添加全局Css文件,如在assets下的Css文件夾目錄下添加了一個index.css文件,然后在nuxt-config.js里配置該css文件路徑即可。 css:['~assers/css/index.css']
通過別名訪問圖片在template里是正確的,為何在Css設置背景圖卻報錯?
在css配置的是,需要將'~/'后面的'/'去除掉。
<img src="~/static/logo.jpg"/> backround-image:url('~static/logo.jpg');
如何添加路由動畫?
同樣,我們在Css文件里添加一些動畫代碼,一般樣式會在其后面添加-active和-leave-active,其實和Vue動畫形式一致。其中以page開頭的動畫,默認會作用于全部頁面,如果想給特定的頁面加動畫,可以在對應的頁面script里引用,如 transitions: 'bounce'即可。
.page-enter-active, .page-leave-active { transition: opacity .3s } .page-enter, .page-leave-active { opacity: 0 } .bounce-enter-active { animation: bounce-in .8s; } .bounce-leave-active { animation: bounce-out .5s; } @keyframes bounce-in { 0% { transform: scale(1) } 50% { transform: scale(1.01) } 100% { transform: scale(1) } } @keyframes bounce-out { 0% { transform: scale(1) } 50% { transform: scale(1.01) } 100% { transform: scale(1) } }
路由參數如何傳遞?
同Vue-router,有聲明式和編程式兩種方式,無非是標簽變成了 router.push(...)
nuxt-link :to="{name:'article',params:{id:1234}}" >聲明式</nuxt-link> // 編程式 this.$router.push({ name:'article', params:{ id:1234 } })
動態路由如何進行參數檢驗?
Nuxt.js提供了一個validate的生命周期鉤子,可以在此進行參數的校驗。以文章詳情校驗id為例,我們需要判斷傳入的id是否是數字,可以像下面這樣處理。
validate({ params }) { return /^\d+$/.test(params.id) }
如何添加404等錯誤頁面?
可以在layout下新建一個error.vue頁面,內容如下,當訪問一個不存在的頁面的時候,或者參數檢驗失敗的時候,或者我們在middleware中間件處理拋出異常的時候,都會跳轉到該頁面。
<template> <div class="container"> <h2 v-if="error.statusCode === 404">頁面不存在</h2> <h2 v-else>應用發生錯誤異常</h2> <nuxt-link to="/">首 頁</nuxt-link> </div> </template> <script> export default { props: ['error'], layout: 'blog' // 指定模板頁面 } </script>
middleware中的文件拋出錯誤
export default function({ store, error, redirect }) { if (!store.state.user.userInfo.auth) { error({ message: '沒有權限哦!', statusCode: 403 }) } }
頂部進度條如何設置?
loading 屬性配置 可以在nuxt-config.js設置loading的顏色,使用了this. loading可能無法在created里立即使用。此種配置loading有嚴重的缺陷,無法知道真正的加載進度。也可以自定義加載組件,loading: '~components/loading.vue'。
export default { mounted () { this.$nextTick(() => { this.$nuxt.$loading.start() setTimeout(() => this.$nuxt.$loading.finish(), 500) }) } }
異步數據如何獲取?
Nuxt.js提供了兩個函數,asyncData和fetch函數。asyncData 獲取組件的數據,fetch 在渲染頁面之前獲取數據填充應用的狀態樹(store)。
asyncData可以使用promise也可以使用async函數,記住,此時返回的東西需要用一個對象進行包裹,不能掛載到data里,此時沒有this對象。
// 方式一 asyncData({ app,params,route,query,error}) { return getUserlist({}).then(res => { let user = []; user = res.list console.log(user,'user') return {user} }) .catch(err => { console.log(err) }) }, // 方式二 async asyncData({ app }) { let data = await getUserlist({}); let user = data.list; return { user } }
fetch函數同上,可以使用promise也可以使用async函數,通常會commit一個mutation。
export default { fetch ({ store, params }) { return axios.get('http://my-api/stars') .then((res) => { store.commit('setStars', res.data) }) } } </script> // 或者使用 async 或 await 的模式簡化代碼如下: <template> <h2>Stars: {{ $store.state.stars }}</h2> </template> <script> export default { async fetch ({ store, params }) { let { data } = await axios.get('http://my-api/stars') store.commit('setStars', data) } } </script>
如何動態修改title的內容?
如果是寫死的,可以直接修改head的配置。
head() { return { // title: '',這里一旦聲明,在asyncdata里修改也不起作用,直接以這個為準 meta: [ { hid: 'description', // nuxt.config 替換唯一標識 hid { hid: 'description', name: 'description', content: 'Nuxt.js project' } name: 'content', content: '文章詳情' } ] } },
如果是動態數據從數據源里獲取,然后通過asynData里的app對象,動態修改head的title。
asyncData({ app, params }) { const id = params.id; return getArticleDetail({ id }) .then(result => { app.head.title = result.title; }) .catch(err => {}) }
如何進行權限JWT驗證?
登錄成功以后,我們會在cookie和Vuex中緩存token信息,當界面刷新的時候,會走store里的nuxtServerInit 函數,該函數僅在每個服務器端渲染中運,可以使用req.headers.cookie獲取瀏覽器的cookie,再次更新store里的值,接著會走到中間件,中間件進行驗證,如果有token信息則繼續,沒有則跳轉到登錄頁。
1. 為什么要在nuxtServerInit更新store的值?
需要在middleware里使用,否則刷新后store里的值為空了。
2. 客戶端調用接口可以拿到token,服務器端如何拿到?
可以通過nuxtServerInit里的req拿到請求信息的cookie,然后請求接口。
3. 前后端分離,刷新的時候如何保證用戶名、token等信息依然存在?
可以像上面一樣,每次取cookie的值再次更新store,但這樣有一個問題,cookie可能會被篡改,后端代碼需要做驗證。也可以每次刷新重新通過token請求接口,更新用戶信息。
store代碼
import Vue from 'vue'; import Vuex from 'vuex'; import user from './modules/user'; import { COOKIE_KEY } from '~/assets/js/constant.js'; Vue.use(Vuex); const store = () => new Vuex.Store({ modules: { user }, actions: { async nuxtServerInit({ commit, dispatch }, { req, app }) { if (req.headers.cookie) { let parsedResult = {}; req.headers.cookie.split(';').forEach(cookie => { const currentCookie = cookie.split('='); parsedResult[currentCookie[0].trim()] = (currentCookie[1] || '').trim(); }); const userInfo = { name: parsedResult[COOKIE_KEY.NAME], token: parsedResult[COOKIE_KEY.TOKEN] }; commit('user/setUserInfo',userInfo); } } } }); export default store;
中間件代碼
export default function({ store, error, redirect }) { if (!store.state.user.userInfo.token || !store.state.user.userInfo.name) { // error({ // message: 'You are not connected', // statusCode: 403 // }) redirect('/'); } }
nginx部署
npm run build
選擇build以后的四個文件: .nuxt, static, nuxt.config.js, package.json上傳到服務器。
pm2 pm2 start npm --name 'package.json.name' -- run start
nginx配置
查看網頁源代碼可以看到:
server{ listen 3000; server_name felix12345.club; gzip on; gzip_buffers 32 4K; gzip_comp_level 6; gzip_min_length 100; gzip_types application/javascript text/css text/xml; gzip_disable "MSIE [1-6]\."; gzip_vary on; proxy_buffer_size 64k; proxy_buffers 32 32k; proxy_busy_buffers_size 128k; location / { root /data/ww/nuxt; proxy_pass http://127.0.0.1:3002; proxy_set_header X-Real-IP $remote_addr; } }
關于使用Nuxt.js怎么實現一個SSR前端博客就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。