Nuxt.js實(shí)戰(zhàn)詳解
一、為什么選擇Nuxt.js
多數(shù)是基于webpack構(gòu)建的項(xiàng)目,編譯出來(lái)的html文件,資源文件都被打包到j(luò)s中,以下圖404頁(yè)面代碼為例。從代碼中可以看出,這樣的頁(yè)面是不利于 搜索引擎優(yōu)化(SEO, Search Engine Optimization) ,并且 內(nèi)容到達(dá)時(shí)間(time-to-content) (或稱(chēng)之為首屏渲染時(shí)長(zhǎng))也有很大的優(yōu)化空間。為了解決以上問(wèn)題,引入了 Nuxt.js 框架。
vue官網(wǎng)對(duì)于Nuxt.js也是很推薦的,除此之外,Nuxt.js的開(kāi)發(fā)者積極活躍,版本迭代迅速。經(jīng)過(guò)一系列rc版本后,終于在1月9日發(fā)布了 v1.0.0 正式版本!

圖1. 使用webpack構(gòu)建的HTML(代碼已格式化)

圖2. 使用 Nuxt.js 構(gòu)建的HTML(代碼已格式化)
二、Nuxt.js 簡(jiǎn)介
Nuxt.js 是一個(gè)基于 Vue.js 的通用應(yīng)用框架,它預(yù)設(shè)了利用 Vue.js 開(kāi)發(fā) 服務(wù)端渲染(SSR, Server Side Render) 的應(yīng)用所需要的各種配置,同時(shí)也可以一鍵生成靜態(tài)站點(diǎn)。
作為框架,Nuxt.js 為 客戶(hù)端/服務(wù)端 這種典型的應(yīng)用架構(gòu)模式提供了許多有用的特性,例如異步數(shù)據(jù)加載、中間件支持、布局支持等。區(qū)別于其他 vue SSR 框架,Nuxt.js 有以下比較明顯的特性。
- 自動(dòng)代碼分層
- 強(qiáng)大的路由功能,支持異步數(shù)據(jù)(路由無(wú)需額外配置)
- HTML頭部標(biāo)簽管理(依賴(lài) vue-meta 實(shí)現(xiàn))
- 內(nèi)置 webpack 配置,無(wú)需額外配置
三、項(xiàng)目實(shí)戰(zhàn)1、項(xiàng)目創(chuàng)建
官方提供了基于 vue-cli 腳手架工具,常用的有如下三個(gè),更多腳手架工具可以查看nuxt-community 。本項(xiàng)目使用的是 express-template。
vue init nuxt-community/starter-template <project-name> vue init nuxt-community/koa-template <project-name> vue init nuxt-community/express-template <project-name>
2、開(kāi)發(fā)
1)目錄結(jié)構(gòu)
├─assets 資源目錄,未編譯的靜態(tài)資源如less、js ├─components 組件目錄 ├─layouts 布局目錄 ├─mock mock數(shù)據(jù) ├─node_modules ├─pages 頁(yè)面目錄 ├─index.vue ├─.... ├─plugins 插件 ├─server express服務(wù) ├─static 靜態(tài)文件目錄 ├─store vuex store ├─utils 工具方法
2)配置
Nuxt.js 默認(rèn)的配置涵蓋了大部分使用情形,也可通過(guò)修改 nuxt.config.js 來(lái)覆蓋默認(rèn)配置。
// nuxt.config.js 文件配置
const path = require('path')
module.exports = {
// Headers of the page
head: {
title: '默認(rèn)共用title',
meta: [
{ charset: 'utf-8' },
{ 'http-equiv': 'pragma', content: 'no-cache' },
{ 'http-equiv': 'cache-control', content: 'no-cache' },
{ 'http-equiv': 'expires', content: '0' },
{ content: 'telephone=no', name: 'format-detection' }
],
// html head 中創(chuàng)建 script 標(biāo)簽
script: [
{ innerHTML: require('./assets/js/flexible_nuxt'), type: 'text/javascript', charset: 'utf-8'}
],
// 不對(duì)<script>標(biāo)簽中內(nèi)容做轉(zhuǎn)義處理
__dangerouslyDisableSanitizers: ['script']
},
// Global CSS
css: ['~/assets/css/reset.css', '~/assets/css/main.less'],
// Global env
env: {
__ENV: process.env.__ENV
},
build: {
vendor: ['axios'],
postcss: [
require('postcss-px2rem')({
remUnit: 75
})
],
extend (config, ctx) {
if (ctx.isClient) {
// 拓展 webpack 配置
config.entry['polyfill'] = ['babel-polyfill']
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
// 添加 alias 配置
Object.assign(config.resolve.alias, {
'utils': path.resolve(__dirname, 'utils')
})
}
}
},
plugins: [{src: '~plugins/toast', ssr: false}, {src: '~plugins/dialog', ssr: false}]
}
HTML頭部標(biāo)簽管理:
Nuxt.js 通過(guò) vue-meta 實(shí)現(xiàn)頭部標(biāo)簽管理,在 nuxt.config.js 中的 head 配置。所有的頁(yè)面都會(huì)走這個(gè)配置,如果想要修改某一頁(yè)面的title,可以在 pages/**.vue 文件下,添加如下配置,這時(shí)該頁(yè)面的標(biāo)題就變成了“收車(chē)費(fèi)”,其余頁(yè)面還保持原有標(biāo)題不變。

在config header配置中, __dangerouslyDisableSanitizers: ['script'] 主要是為了不對(duì)<script>標(biāo)簽中內(nèi)容做轉(zhuǎn)義處理??聪旅娴睦?#127792;:
head: {
title: 'myTitle',
meta: [
{ charset: 'utf-8' },
{ 'http-equiv': 'pragma', content: 'no-cache' },
{ 'http-equiv': 'cache-control', content: 'no-cache' },
{ 'http-equiv': 'expires', content: '0' },
{ content: 'telephone=no', name: 'format-detection' }
],
script: [
{ innerHTML: 'console.log("hello")', type: 'text/javascript', charset: 'utf-8'}
]
},
生成 html:
<script data-n-head="true" type="text/javascript" charset="utf-8">console.log("hello")</script>
我們發(fā)現(xiàn) vue-meta 把引號(hào)做了轉(zhuǎn)義處理,加入 __dangerouslyDisableSanitizers: ['script'] 后,就不會(huì)再對(duì)這些字符做轉(zhuǎn)義了,該字段使用需慎重!
3)路由
Nuxt.js 依據(jù) pages 目錄結(jié)構(gòu),自動(dòng)生成 vue-router 模塊的路由配置。
假設(shè) pages 的目錄結(jié)構(gòu)如下:

那么,Nuxt.js 自動(dòng)生成的路由配置如下:

嵌套路由:
創(chuàng)建內(nèi)嵌子路由,需要添加一個(gè) Vue 文件,同時(shí)添加一個(gè)與該文件同名的目錄用來(lái)存放子視圖組件。在父級(jí) Vue 文件內(nèi)增加 <nuxt-child/> 用于顯示子視圖內(nèi)容。
4)布局
Nuxt.js布局方式如下圖所示:

layouts對(duì)應(yīng)目錄中的layouts文件夾,默認(rèn)pages下的頁(yè)面走的都是 layouts/default.vue 布局方式,如下圖。其中<nuxt/>可以類(lèi)似vue中slot插槽的概念,pages/**.vue中的內(nèi)容會(huì)插在<nuxt/>內(nèi)。

此外,如果想要某一頁(yè)面,不走默認(rèn)布局方式,可以在vue文件中配置layouts,如下。
<script>
export default {
layout: 'demo_layout',
...
}
</script>
5)vuex
在根目錄創(chuàng)建 store 目錄,就會(huì)默認(rèn)引用 vuex 模塊,除此之外,還進(jìn)行了以下的操作:1)將 vuex 模塊 加到 vendors 構(gòu)建配置中去;2)設(shè)置 Vue 根實(shí)例的 store 配置項(xiàng)。
Nuxt.js 支持兩種使用 store 的方式:
- 普通方式:store/index.js 返回一個(gè) Vuex.Store 實(shí)例
- 模塊方式:store 目錄下的每個(gè) .js 文件會(huì)被轉(zhuǎn)換成為狀態(tài)樹(shù)指定命名的子模塊 (當(dāng)然,index 是根模塊,相當(dāng)于設(shè)置了namespaced: true)
Nuxt.js提供了模塊方式的簡(jiǎn)單寫(xiě)法:使用狀態(tài)樹(shù)模塊化的方式,store/index.js 不需要返回 Vuex.Store 實(shí)例,直接將 state、mutations 和 actions 暴露出來(lái)即可。示例如下:
export const state = () => ({
accesstoken: ''
})
export const mutations = {
setAccesstoken (state, accesstoken) {
state.accesstoken = accesstoken
}
}
6)異步數(shù)據(jù) asyncData
Nuxt.js 增加了一個(gè) asyncData 方法,用于 在設(shè)置組件數(shù)據(jù) 之前 能夠異步獲取 或 處理數(shù)據(jù)。
由于 asyncData 是在組件 初始化 之前被調(diào)用的,所以不能通過(guò) this 引用組件的實(shí)例對(duì)象,可以使用上下文對(duì)象來(lái)實(shí)現(xiàn)某些功能,可參考 context api
示例🌰:
asyncData (params) {
let accesstoken = params.route.query.accesstoken
// request 基于 axios 封裝的函數(shù)
return request({
url: '/drivers/banks',
method: 'get',
headers: {
accesstoken
}
})
.then(res => {
let {
bankInfo
} = res.data
return {
banksData: bankInfo,
accesstoken
}
})
.catch(err => {
return error({ message: 'accesstoken not found', statusCode: 404 })
})
}
上述代碼,會(huì)在 組件初始化 之前,請(qǐng)求'/drivers/banks'接口,接口返回的數(shù)據(jù)會(huì) 融合在 data 中,一并返回模版顯示。在瀏覽器中,使用Vue DevTools可以清晰的查看到 banksData, accesstoken 都在data中。
在調(diào)試中發(fā)現(xiàn),刷新頁(yè)面時(shí),該請(qǐng)求是在服務(wù)端發(fā)送的,由其他頁(yè)面回退到該頁(yè)面時(shí),請(qǐng)求是在客戶(hù)端發(fā)送的。
7)fecth方法
與 asyncData 方法類(lèi)似,不同的是它不會(huì)設(shè)置組件的數(shù)據(jù),作用是設(shè)置 store 數(shù)據(jù)。
五、總結(jié)
本項(xiàng)目在開(kāi)發(fā)中,使用的是 1.0.0-rc9 版本,我們正在積極嘗試遷移到 1.0.0 正式版本。但是,1.0.0-rc9 版本,未見(jiàn)明顯問(wèn)題,比較穩(wěn)定,足以投入到生產(chǎn)中。
本文主要介紹 Nuxt.js 的特性,后面還會(huì)和大家分享踩的坑。文中有任何表述不清或不當(dāng)?shù)牡胤?,歡迎大家批評(píng)指正。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue使用echarts畫(huà)組織結(jié)構(gòu)圖
這篇文章主要介紹了vue使用echarts畫(huà)組織結(jié)構(gòu)圖的示例,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2021-02-02
FastApi+Vue+LayUI實(shí)現(xiàn)前后端分離的示例代碼
本文主要介紹了FastApi+Vue+LayUI實(shí)現(xiàn)前后端分離的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Vue 實(shí)現(xiàn)高級(jí)穿梭框 Transfer 封裝過(guò)程
本文介紹了基于Vue2和Element-UI實(shí)現(xiàn)的高級(jí)穿梭框組件Transfer的設(shè)計(jì)與技術(shù)方案,組件支持多項(xiàng)選擇,并能實(shí)時(shí)同步已選擇項(xiàng),包含豎版和橫版設(shè)計(jì)稿,并提供了組件的使用方法和源碼,此組件具備本地分頁(yè)和搜索功能,適用于需要在兩個(gè)列表間進(jìn)行數(shù)據(jù)選擇和同步的場(chǎng)景2024-09-09
vue對(duì)el-autocomplete二次封裝增加下拉分頁(yè)
項(xiàng)目中的聯(lián)想輸入框現(xiàn)在都是采用的el-autocomplete實(shí)現(xiàn)的,但是數(shù)據(jù)增多就會(huì)需要做分頁(yè)處理,本文主要介紹了vue對(duì)el-autocomplete二次封裝增加下拉分頁(yè),感興趣的可以了解一下2022-03-03
Vue引入jquery實(shí)現(xiàn)平滑滾動(dòng)到指定位置
這篇文章主要介紹了Vue引入jquery實(shí)現(xiàn)平滑滾動(dòng)到指定位置的效果,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05
vue router點(diǎn)擊打開(kāi)新的標(biāo)簽頁(yè)的方法(最新推薦)
vue router點(diǎn)擊打開(kāi)新的標(biāo)簽頁(yè)的方法,只需要在router-link中加入target="_blank"即可在新的頁(yè)面打開(kāi)標(biāo)簽,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10

