1. 程式人生 > >VUE SSR伺服器端渲染NUXT採坑總結

VUE SSR伺服器端渲染NUXT採坑總結

初始化建立專案

yarn create nuxt-app <專案名>

css預編譯

安裝 yarn add node-sass scss-loader sass-loader --save-dev

路由管理

在nuxt中路由已經被整合到框架中,所以不需要再單獨引入配置,而且當頁面檔案建立後, router會生成響應的路由,路由檔案在.nuxt/router.js檔案,用法上基本不變, 與vue-router用法不同部分記錄如下

跳轉與傳參

  • nuxt路由跳轉同樣是分為兩種方式(宣告式和程式設計式),不同的是在nuxt中用跳轉標籤nuxt-link而不是router-link
  • 傳參demo如下
 1  <nuxt-link :to="{name:'home',params:{newsId:3306}}">home1</nuxt-link>
 2     接收引數
 3     asyncData({ params }) {
 4         console.log('home1', params);
 5     },
 6     <nuxt-link :to="{path:'home',query:{newsId:3306}}">home2</nuxt-link>
 7     接收引數
 8     asyncData({ query }) {
 9         console.log('home2', query);
10     },

頁面切換動效

路由動效分為全域性動效和單獨頁面動效

  • 建立動效檔案,在asset檔案下建立動效樣式檔案(這裡定義檔名changePage.css)
  • 定義動畫效果,這裡定義簡單的淡入淡出效果
// 頁面預設的頁面切換類名為page-enter、page-enter-active、page-leave-active
.page-enter-active,
.page-leave-active {
  transition: opacity 1s;
}

.page-enter,
.page-leave-active {
  opacity: 0;
}

引入定義的動效檔案,在nuxt.config.js檔案中配置中引入該css檔案

 

 

 定義單獨頁面動效

  • 在頁面檔案中定義樣式類名
1 export default {
2     transition: 'home'
3 }

在css檔案中定義動畫效果

.home-enter-active,
.home-leave-active {
  transition: all 2s;
  font-size: 12px;

}

.home-enter,
.home-leave-active {
  opacity: 0;
  font-size: 40px;
}

巢狀路由

開發業務中,有時難免會遇到需要二級甚至多層路由巢狀,官方文件中的二級路由介紹也是過於簡單,為此又多掉了幾根頭髮 這裡就拿官網文件的例子作為講解

 1 第一:假設要建立一個user的二級路由,檔案結構如:
 2 
 3 pages/
 4 --| users/  //2、最容易建立與user.vue檔案同名的資料夾,這樣nuxt就會識別出我們的意圖,原來是要建立巢狀路由
 5             //假如資料夾與user.vue不同名,那麼該資料夾下的檔案同樣被生成一級路由
 6 -----| _id.vue
 7 -----| index.vue
 8 --| users.vue // 1、首先要有user.vue檔案
 9 
10 第二:Nuxt.js 自動生成的路由配置如下:
11 router: {
12   routes: [
13     {
14       path: '/users',
15       component: 'pages/users.vue',
16       children: [
17         {
18           path: '',
19           component: 'pages/users/index.vue',
20           name: 'users'
21         },
22         {
23           path: ':id',
24           component: 'pages/users/_id.vue',
25           name: 'users-id'
26         }
27       ]
28     }
29   ]
30 }
31 第三:在一級頁面中顯示二級頁面
32 <template>
33     <div class="page-me">
34         <div>一級頁面的相關內容、、、</div>
35         <nuxt-child /> //二級頁面的檢視視窗,相當於Vue Router的<router-view></router-view>
36     </div>
37 </template>

路由攔截/鑑權

nuxt的路由攔截與Vue Router不同,需要引入中介軟體 的概念,好在文件介紹比較容易理解,現梳理如下

  • 需要在指定的資料夾middleware/ 下建立路由攔截檔案(檔案不限數量)
  • 一箇中間件接收 context 作為第一個引數,context包含了包括vuex等在內相關資料資訊,以此通過資料執行相關邏輯
export default function (context) {
  context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent
}

在nuxt.config.js為全域性頁面定義路由攔截

module.exports = {
  router: {
    middleware: 'stats'//中介軟體檔名
  }
}

當然不想全域性定義路由攔截也可以為單獨的頁面定義路由攔截

//具體的頁面
export default {
  middleware: 'stats'
}

錯誤頁設定

一個完成專案,404或其他錯誤頁面總是要有的,對此nuxt已經封裝了404頁面跳轉,在layouts資料夾下建立error.vue檔案(檔名必須是error.vue),元件接收error物件引數,通過引數的狀態碼判斷頁面錯誤原因

<template>
    <div class="container">
        <h2 v-if="error.statusCode == 404">這是404頁面</h2>
        <h2 v-else>這是500頁面</h2>
    </div>
</template>
<script>
export default {
    props: ['error'], //nuxt已經封裝好返回的
    mounted() {
        console.log('error', this.error);
    }
};
</script>

介面請求

安裝

  • 安裝:yarn add @nuxtjs/axios
  • 同正常的axios用法相同,不做詳細解釋

本地代理

  • npm i @nuxtjs/proxy -D
  • 在 nuxt.config.js 配置檔案中新增對應的模組,並設定代理
  • 配置了代理,本地開發時axios就不能使用baseURL(打包時,baseURL還是需要放開)
 1 modules: ['@nuxtjs/axios','@nuxtjs/proxy'],
 2 axios: {
 3     proxy: true
 4 },
 5 proxy: {//代理可以設定多個
 6     '/api': {//  /api是指真實介面域名後的一個層級
 7         target: 'http://example.com',//真實介面域名
 8         pathRewrite: {
 9             '^/api' : '/'// "/api"與上面的api相同
10         }
11     }
12 }

axios API封裝

  • axios的封裝與常規vue專案相同,不同的區別是需要在配置檔案中將封裝檔案引入
plugins: ["@/plugins/element-ui", "~/plugins/api.js"]

 

api訪問本地開發

通過設定IP地址,這樣就可以通過IP訪問本地專案環境

//package.json中配置
"devDependencies": {},
  "config": {
    "nuxt": {
      "host": "0.0.0.0",
      "port": "5000"
    }
  }

asyncData

用於服務端或路由更新之前被呼叫(如果這裡進行介面請求,頁面會等介面返回結果後才發生跳轉),方法的第一個引數被設定為當前頁面的上下文物件(即包含路由、引數等等的一些列資訊),可用於請求一個或多個介面,並將返回的資料融合到元件的data中,改方法與mounted函式同級,只在頁面模組的檔案內生效,在元件模組檔案內不生效,由於asyncData方法是在元件 初始化 前被呼叫的,所以在方法內是沒有辦法通過 this 來引用元件的例項物件。

寫法一
asyncData(context) {
    return (
        axios.get('https://api.myjson.com/bins/8gdmr1').then(res => {
            return { info: res.data };
            //注意,return返回的最好是key:value物件,直接return導致不利於從例項data中查詢使用,如:
            //return (res.data),因為沒有設定key,返回的資料雖然融合到例項的data上,但沒有key則沒法通過key值查詢使用
        }),
        axios.get('https://api.myjson.com/bins/8gdmr').then(res => {
            return { info: res.data };
        })
    );
},
寫法二
async asyncData({ params }) {
    const { data } = await axios.get('https://api.myjson.com/bins/8gdmr');
    return { info: data };
},

Vuex

nuxt中集成了vuex,不需要新安裝外掛,Nuxt.js 會嘗試找到應用根目錄下的 store 目錄,並引用 vuex 模組,將 vuex 模組 加到 vendors 構建配置中去,設定 Vue 根例項的 store 配置項。

以上是官方文件原話,大白話翻譯就是:nuxt已經集成了vuex不需要手動安裝,nuxt會直接找到vuex檔案,並把vuex配置到專案中,然後就想正常vue一樣使用即可

建立與使用

  • 1、vuex不需要新建立例項,即不需要new Vuex.Store({})
  • 2、state的值應該始終是function,為了避免返回引用型別,會導致多個例項相互影響,即
//正確寫法
export const state = () => ({
  counter: 0
})
//錯誤寫法
export const state = {
  counter: 0
}

資料持久化

為避免頁面重新整理資料狀態丟失,需要對vuex資料持久化,nuxt的vuex資料持久化與vue專案稍有不同,這裡推薦的是nuxt-vuex-localstorage

  • 安裝
  • 配置檔案引入
//nuxt.config檔案中引入
modules: ["nuxt-vuex-localstorage"]

歡迎大佬指教

專案中雖然在使用vuex,但遇到的問題依然很多,使用起來總是磕磕絆絆,歡迎留言指教

部分配置介紹

meta標籤設定

既然是為了SEO優化,那麼總是少不了mate標籤關鍵字設定,mate標籤分為定義全域性和單個頁面配置

  • 配置檔案定義全域性
head: {
    title: process.env.npm_package_name || "",
    meta: [
        { charset: "utf-8" },
        {
            name: "viewport",
            content: "width=device-width, initial-scale=1"
        },
        {
            hid: "description",
            name: "description",
            content: process.env.npm_package_description || ""
        }
    ],
    link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }]
},

設定頁面獨有關鍵字

export default {
  data () {
    return {
      title: 'Hello World!'
    }
  },
  head () {
    return {
      title: this.title,
      meta: [
        { hid: 'description', name: 'description', content: 'My custom description' }
      ]
    }
  }
}