Nuxt.js
Vue提供了服務端渲染及還能支撐spa單頁功能的框架。Nuxt.js 主要關注的是應⽤的 UI渲染。功能強大,方便我們快速上手。開箱即用。特點:
- 模塊化
- 高效快速
- 開發體驗
- 靜態⽂件服務 & 強大路由功能
安裝: Nuxt模板項目 官方推薦 npx 這樣會安裝最新模板。然後進入項目。運行
npx create-nuxt-app <項目名>
cd <項目名>
npm run dev
然後選擇你自己需要的插件依賴,不知道可以一直選默認;
整體項目目錄結構
- assets:資源目錄assets
用於組織未編譯的靜態資源如LESS、SASS 或JavaScript。 - components:組件目錄components 用於組織應用的Vue.js組件。Nuxt.js 不會擴展增強該目
錄下Vue.js組件,即這些組件不會像頁面組件那樣有asyncData 方法的特性。 - layouts:佈局目錄layouts 用於組織應用的佈局組件。
- middleware:中間件目錄用於存放應用的中間件。
- pages:頁面目錄
pages用於組織應用的路由及視圖。Nuxt.js 框架讀取該目錄下所有的. vue
文件並自動生成對應的路由配置。 - plugins:插件目錄plugins 用於組織那些需要在根vue. js應用實例化之前需要運行的
Javascript插件。 - static:靜態文件目錄
static用於存放應用的靜態文件,此類文件不會被Nuxt,js調用Webpack
進行構建編譯處理。服務器啓動的時候,該目錄下的文件會映射至應用的根路徑/下。 - store:用於組織應用的Vuex狀態樹文件。Nuxt.js 框架集成了Vuex狀態樹的相關功能配置,
在store目錄下創建一個index. js |文件可激活這些配置。 - nuxt.config.js:該文件用於個性化配置Nuxt應用。
路由
-
路由自動生成
page 文件中的路由 .vue 文件。可以自動生成以文件名爲路由名生成。特高效率
page/user.vue => http://localhost:3000/user 則生成這樣目錄
檢查生成的路由配置,在.next 文件中 router.js。
-
嵌套路由
Nuxt 中在page目錄下得出現 .vue 同名的文件才能出發嵌套利用。不然你在 page中創建其他文件,在文件中創建其他 .vue 文件事,只能生成路徑的嵌套。
-
錯誤示範:目錄:/page/user/getUserInfo.vue => http://localhost:3000/user/getUserInfo
路徑看上去可以,可是去路由配置看發現getUserInfo路由和user是同級路由。
-
正確寫法:
- 在page創建父頁面: 如 user.vue
- 在父頁面 user.vue 中使用
nuxt-child
標籤。他類似 router-view - page創建包裹子路由的文件夾,且父親同名:page/user
- 比如: 創建子路由 用戶個人信息。page/user/userOne.vue => localhost:3000/user/userOne
文件中可以繼續創建文件,繼續多級嵌套路由。方法同理
-
-
路由傳參
路徑跳轉給下一個頁面傳遞參數。
_id.vue {{ $route.parmas.id }} =》 /user/99 則99就是id參數
- 多參數傳值: 需要繼續嵌套文件。例如: 繼續嵌套更新 /user/id/name 。這樣想id和name做參數,步驟
- 1創建_id.vue 並在頁面使用 nuxt-child 標籤
- 2創建**_id** 文件夾 在文件內 創建_name.vue
- 3在
_id.vue
和_name.vue
都可以使用 $route.parmas 查看參數了
-
路由跳轉
nuxt-link 標籤. 和roter-link 用法一樣。指定的頁面 默認預加載。提供良好的體驗
如果不想預加載 銷燬第一資源,可以使用 no-prefetch 取消。點擊頁面纔去加載。
-
自定義路由配置
如果Nuxt默認生成利用方式 不滿足自己開發。那麼你可以在 nuxt.config.js 中修改。如替換默認別名。參數,傳參方式等等…
//router 自定義路由配置 滿足自己需要 router: { extendRoutes(routes, resolve) { routes.push({ path: '/foo', //替換默認 也可訪問foo,就可以訪問hzfFoo.vue component: resolve(__dirname, 'pages/hzfFoo.vue'); }) }, },
layout 全局佈局
Nuxt默認佈局是 default.vue。如果你希望你的登錄註冊也,和後臺頁區分開,可以自己定義登錄佈局
- 自定義佈局
- 定義佈局 login.vue
<template>
<div>
歡迎登錄 登錄
<!-- page文件中所有頁面 -->
<nuxt />
</div>
</template>
- 使用自定義佈局
export default {
layout: 'login',
...
}
-
捕獲錯誤佈局頁
在layout中定義 error.vue
<template> <div class="container"> <h1 v-if="error.statusCode === 404">頁面不存在</h1> <h1 v-else>應用發生錯誤異常</h1> <p>{{error}}</p> <nuxt-link to="/">首 頁</nuxt-link> </div> </template> <script> export default { props: ['error'], layout: 'blank' } </script>
頁面頭部信息設置
Nuxt生成的頁面不在是以前那樣只有一個index.html。現在是多個頁面。那麼可以通過head() 方法,給頁面自定義頭部信息
export default {
head() {
return {
title: '個人主頁大全',
// vue-meta利用hid確定要更新meta 判斷是否和首頁一樣,一樣就給替換
meta: [
{
name: "description", hid: "description",
content: "這個網頁主要展示你的個人用戶信息,愛好,性別,年齡等..."
}
],
link: [{ rel: "icon", href: "https://img.kaikeba.com/kkb_portal_icon.ico" }]
}
},
}
異步數據獲取
當我需要請求接口數據,就需要異步處理。Nuxt提供了專門的函數。
asyncDate()
該方法可以讓我設置組件數據之前。獲得異步數據或者處理數據.
- 參數方式使用{ xxx } ES6解構自取。例如:
async asyncData({ $axios, params, error })
- $axios: 接口調用
- params: 路由參數
- error: 傳遞錯誤信息,給會跳轉到默認錯誤頁面顯示
- 返回對象。該對象函數的對象類型。他用來合併data()中的數據,這樣異步獲取的數據就映射到data中
案例演示-步驟:
-
安裝axios
npm install @nuxtjs/axios -S
-
配置axios 在nuxt.config.js
modules: [ '@nuxtjs/axios', ], axios: { proxy: true }, proxy: { // 餓了麼 "/restapi": "https://h5.ele.me" },
-
asyncData調用axios , 修改配置文件記得重啓;
async asyncData({ $axios, params, error }) { // 這個方法執行時間很早,沒有this。所以不能用this.route.params //const data = await $axios.get('/xxx'); // $get 直接只返回data 不用開發者自己去點出來 const data = await $axios.$get('/restapi/bgs/poi/search_poi_nearby_alipay?keyword=廣州&offset=0&limit=20'); console.log(data); if (Array.isArray(data) && data.length > 0) { // asyncData 返回對象 會和data中的對象合併, return { list: data } } error({ statusCode: 400, message: '失敗--'}) }
中間件
很類似於路由守衛,可以全局,也可以局部到某個頁面。頁面每次切換都會執行,可以做一些權限的判斷
-
在
middleware
文件中定義 例如:auth.jsexport default function ({ route, redirect, store }) { console.log(route); //路由 console.log(redirect); // 路由跳轉回調 console.log(store); // vuex //redirect('/login') }
-
全局 在nuxt.config.js 中
module.expors = { router: { middleware: ['auth'] } }
-
局部
export default { // 局部中間件 middleware: ["auth"] }
.vue文件其他常用配置
Nuxt和常規Vue頁面配置中,出現了很多變化。比如: anyncData() 函數比創建之前還早執行的。或者fecth函數,這些都是爲開發者提供更多開發體驗。
- anyncData() > 組件創造之前就最早執行,如果是首屏則是先是
nuxtServerInit
- fecth() > 和anyncData類似獲取會在組件創造之前執行。不過在anyncData後面 並且 fetch ⽅法不會設
置組件的數據 - head() > 設定HTML的頭部信息
- layout: “” > 設定使用的佈局是那個
- middleware: [""] > 設定中間件名稱
- transition: Nuxt.js 使用 Vue.js transition組件來實現路由切換時的過渡動效
- scrollToTop: true/false > 屬性用於控制頁面渲染前是否滾動至頁面頂部
- validate: 可以讓你在動態路由對應的頁面組件中配置一個校驗方法用於校驗動態路由參數的有效性
- loading: 手動設置頁面進度條時間顏色大小等。也可以nuxt.config.js全局配置
- 參考:https://zh.nuxtjs.org/api/configuration-loading/
stroe文件 vuex狀態管理
Nuxt 也提供了Vuex的狀態樹管理嵌入在其中,不用安裝即可使用,可在根目錄 store
文件夾中定義
演示案例:
-
在
stroe
中創建user.js 管理用戶數據狀態export const state = () => ({ token: 'null token' }); export const mutations = { init(state, token) { state.token = token; } }; export const getters = { isLogin(state) { return !!state.token; } }; export const actions = { // 異步登錄 login({ commit, getters }, params) { Promise.resolve().then(() => { commit("init", params); return getters.isLogin; }) } };
-
在login.vue 中使用它:注意。dispatch調用指定名稱
onLogin() { //調用store/user.js 下的 login 異步方法 this.$store.dispatch("user/login", 'toKen sxw*&s1n76%$').then(red => { console.log(red); const redirect = this.$route.query.redirect || '/'; this.$router.push(redirect) }) }
nuxtServerInit 首屏獲取服務端數據
有時候當我刷新頁面。發現保存後臺的數據狀態就沒有了,這個時候我們可以使用 nuxtServerInit
函數解決。頁面重新刷新[首屏] 時候,可以執行,拿到服務端數據,然後在保存當我們狀態中
演示: 在store 文件中創建 index.js 注意:nuxtServerInit
只能用 store/index.js 中,且在服務端執行
export const actions = {
// 參數1: 組件上下文
// 參數2: 服務端事例
nuxtServerInit({ commit }, { app }) {
console.log('我在服務端執行了');
// 重新給用戶存值
commit('user/init', 'store index token: 12345')
}
};
插件 Plugins
plugins 可謂是nuxt必備必會的。**他和中間件有些類似,但是邏輯不通,他只會在事例創建之前執行一次。而中間每次路由切換都會執行;**開發中會經常涉及一下初始化工作,例如:安裝插件,elementUI, 以及他的語言。或者設置axios 請求頭攜帶took,或者給給她注入方法
演示案例 上下文中注入全局方法:
-
在plugins 文件夾中 創建
api-inject.js
/* * 參數1: 是vue上下文,我們可以結構取值想要的對象或屬性。 * 參數2: 注入函數 * */ export default ({ $axios }, inject) => { // 在這裏注入一個全局方法 , 那麼以後我們在vue實例中即可用 this.$getCity 函數 // 參數 【函數名稱, 接受參數】 inject("getCity", potions => { console.log(potions); const url = "https://shadow.elemecdn.com/lib/[email protected]/city_list.json" return $axios.$get(url); }); };
-
在nuxt.config.js 中配置
module.exports = { ... plugins: [ "@/plugins/api-inject" ], }
-
可以在全局使用它:
methods: { onGetCity() { this.$getCity('深圳').then(res => { this.list = res }) } }
演示案例 攔截axios請求 設置請求頭token
-
在plugins 文件中創建 interceptor.js 然後在 nuxt.config.js 配置
// 1 interceptor.js中定義函數 export default function({ $axios, store }) { // onRequest 是請求之前執行函數 詳細文檔: @nuxt-axios $axios.onRequest(config => { if (store.state.user.token) { console.log('請求之前 token:', store.state.user.token); // config.headers.Authorization = "Bearer " + store.state.user.token; } return config; }); // 請求響應 $axios.onResponse(config=>{ //判斷請求回來的code .... return config; }) } // 2 nuxt.config plugins: [ "@/plugins/api-inject", "@/plugins/interceptor", ],
項目部署發佈
當我項目完成時候,需要打包上線。發佈到外網。nuxt提供2中方式打包。
-
服務端渲染應用部署
他會以往vue打包部署很相似。打包後生成的文件在 .next/dist 目錄中
npm run build npm start
如何你電腦就是服務器 那麼使用nginx 代理端口後,執行完事。外網可以訪問了,提前你服務器裝node
-
靜態應⽤部署
這種方式會每個頁面都打包出一和html頁面。提前是 渲染和接⼝服務器都需要處於啓動狀態 這樣打包的話效率很好,因爲服務端已經渲染過瀏覽器不用重新渲染。 生成文件在 根目錄/dist 中
npm run generate
導報出來的文件,就和我們Jquery時代的目錄差不多了,都是html頁面
開發中額外注意點
- 首屏時候看不到瀏覽器的接口請求,原因:首屏已經服務端執行了,所以不同瀏覽執行