nuxt.js簡單的說是Vue.js的通用框架,最經常使用的就是用來做SSR(服務器端渲染).Vue.js是開發SPA(單頁應用)的,Nuxt.js這個框架,用Vue開發多頁應用,並在服務端完成渲染,能夠直接用命令把咱們製做的vue項目生成爲靜態html。javascript
主要的緣由時SPA(單頁應用)不利於搜索引擎的SEO操做,Nuxt.js適合做新聞、博客、電影、諮詢這樣的須要搜索引擎提供流量的項目。若是你要做移動端的項目,就不必使用這個框架了。css
在認識SSR
以前,首先對CSR
與SSR
之間作個對比。html
首先看一下傳統的web開發,傳統的web開發是,客戶端向服務端發送請求,服務端查詢數據庫,拼接HTML
字符串(模板),經過一系列的數據處理以後,把整理好的HTML
返回給客戶端,瀏覽器至關於打開了一個頁面。這種好比咱們常常據說過的jsp
,PHP
,aspx
也就是傳統的MVC
的開發。前端
SPA
應用,到了Vue
、React
,單頁面應用優秀的用戶體驗,逐漸成爲了主流,頁面總體式javaScript
渲染出來的,稱之爲客戶端渲染CSR
。SPA
渲染過程。由客戶端訪問URL
發送請求到服務端,返回HTML
結構(可是SPA
的返回的HTML
結構是很是的小的,只有一個基本的結構,如第一段代碼所示)。客戶端接收到返回結果以後,在客戶端開始渲染HTML
,渲染時執行對應javaScript
,最後渲染template
,渲染完成以後,再次向服務端發送數據請求,注意這裏時數據請求,服務端返回json
格式數據。客戶端接收數據,而後完成最終渲染。vue
SPA
雖然給服務器減輕了壓力,可是也是有缺點的:java
JavaScript
加載完畢,而且執行完畢,才能渲染出首屏。SEO
不友好:爬蟲只能拿到一個div
元素,認爲頁面是空的,不利於SEO
。爲了解決如上兩個問題,出現了SSR
解決方案,後端渲染出首屏的DOM
結構返回,前端拿到內容帶上首屏,後續的頁面操做,再用單頁面路由和渲染,稱之爲服務端渲染(SSR
)。node
SSR
渲染流程是這樣的,客戶端發送URL
請求到服務端,服務端讀取對應的url
的模板信息,在服務端作出html
和數據
的渲染,渲染完成以後返回html
結構,客戶端這時拿到的以後首屏頁面的html
結構。因此用戶在瀏覽首屏的時候速度會很快,由於客戶端不須要再次發送ajax
請求。並非作了SSR
咱們的頁面就不屬於SPA
應用了,它仍然是一個獨立的spa
應用。android
SSR
是處於CSR
與SPA
應用之間的一個折中的方案,在渲染首屏的時候在服務端作出了渲染,注意僅僅是首屏,其餘頁面仍是須要在客戶端渲染的,在服務端
接收到請求以後而且渲染出首屏頁面,會攜帶着剩餘的路由信息預留給客戶端
去渲染其餘路由的頁面。webpack
Nuxt.js是特色(優勢):ios
Vue
EcmaScript6
和EcmaScript7
的語法支持JavaScript
和Css
HTML
頭部標籤管理ESLint
SASS
、LESS
等等HTTP/2
推送在使用npm前你須要安裝Node到系統中。若沒有安裝參考此連接 www.cnblogs.com/zhouyu2017/…
(1)用npm來安裝vue-cli這個框架。
npm install vue-cli -g
複製代碼
安裝完成後可使用vue -V 來測試是否安裝成功。(注意:這裏要使用大寫的V,小寫無效)。
(2)使用vue安裝 nuxt
安裝好vue-cli後,就可使用init命令來初始化Nuxt.js項目。
vue init nuxt/starter
複製代碼
這時候他會在github上下載模版,而後會詢問你項目的名稱叫什麼,做者什麼的,這些徹底能夠根據本身的愛好填寫。
(3)使用npm install安裝依賴包
npm install
複製代碼
這個過程是要等一會的,若是你這個過程安裝失敗,能夠直接誒刪除項目中的node_modules文件夾後,從新npm install進行安裝。
(4)使用npm run dev 啓動服務
(5)在瀏覽器輸入 localhost:3000,能夠看到結果,以下:
npm i create-nuxt-app -g create-nuxt-app my-nuxt-demo cd my-nuxt-demo npm run dev 複製代碼
安裝嚮導:
Project name // 項目名稱 Project description // 項目描述 Use a custom server framework // 選擇服務器框架 Choose features to install // 選擇安裝的特性 Use a custom UI framework // 選擇UI框架 Use a custom test framework // 測試框架 Choose rendering mode // 渲染模式 Universal // 渲染全部鏈接頁面 Single Page App // 只渲染當前頁面 複製代碼
一個完整的服務器請求到渲染的流程
經過上面的流程圖能夠看出,當一個客戶端請求進入的時候,服務端有經過nuxtServerInit
這個命令執行在Store
的action
中,在這裏接收到客戶端請求的時候,能夠將一些客戶端信息存儲到Store
中,也就是說能夠把在服務端存儲的一些客戶端的一些登陸信息存儲到Store
中。以後使用了中間件
機制,中間件其實就是一個函數,會在每一個路由執行以前去執行,在這裏能夠作不少事情,或者說能夠理解爲是路由器的攔截器的做用。而後再validate
執行的時候對客戶端攜帶的參數進行校驗,在asyncData
與fetch
進入正式的渲染週期,asyncData
向服務端獲取數據,把請求到的數據合併到Vue
中的data
中,
└─my-nuxt-demo
├─.nuxt // Nuxt自動生成,臨時的用於編輯的文件,build
├─assets // 用於組織未編譯的靜態資源如LESS、SASS或JavaScript,對於不須要經過 Webpack 處理的靜態資源文件,能夠放置在 static 目錄中
├─components // 用於本身編寫的Vue組件,好比日曆組件、分頁組件
├─layouts // 佈局目錄,用於組織應用的佈局組件,不可更改⭐
├─middleware // 用於存放中間件
├─node_modules
├─pages // 用於組織應用的路由及視圖,Nuxt.js根據該目錄結構自動生成對應的路由配置,文件名不可更改⭐
├─plugins // 用於組織那些須要在 根vue.js應用 實例化以前須要運行的 Javascript 插件。
├─static // 用於存放應用的靜態文件,此類文件不會被 Nuxt.js 調用 Webpack 進行構建編譯處理。 服務器啓動的時候,該目錄下的文件會映射至應用的根路徑 / 下。文件夾名不可更改。⭐
└─store // 用於組織應用的Vuex 狀態管理。文件夾名不可更改。⭐
├─.editorconfig // 開發工具格式配置
├─.eslintrc.js // ESLint的配置文件,用於檢查代碼格式
├─.gitignore // 配置git忽略文件
├─nuxt.config.js // 用於組織Nuxt.js 應用的個性化配置,以便覆蓋默認配置。文件名不可更改。⭐
├─package-lock.json // npm自動生成,用於幫助package的統一設置的,yarn也有相同的操做
├─package.json // npm 包管理配置文件
├─README.md
複製代碼
const pkg = require('./package') module.exports = { mode: 'universal', // 當前渲染使用模式 head: { // 頁面head配置信息 title: pkg.name, // title meta: [ // meat { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: pkg.description } ], link: [ // favicon,若引用css不會進行打包處理 { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } ] }, loading: { color: '#fff' }, // 頁面進度條 css: [ // 全局css(會進行webpack打包處理) 'element-ui/lib/theme-chalk/index.css' ], plugins: [ // 插件 '@/plugins/element-ui' ], modules: [ // 模塊 '@nuxtjs/axios', ], axios: {}, build: { // 打包 transpile: [/^element-ui/], extend(config, ctx) { // webpack自定義配置 } } } 複製代碼
{ "scripts": { // 開發環境 "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server", // 打包 "build": "nuxt build", // 在服務端運行 "start": "cross-env NODE_ENV=production node server/index.js", // 生成靜態頁面 "generate": "nuxt generate" } } 複製代碼
開發中常常會遇到端口被佔用或者指定IP的狀況。咱們須要在根目錄下的package.json裏對config項進行配置。好比如今咱們想把IP配置成127.0.0.1,端口設置1000。
/package.json
"config":{
"nuxt":{
"host":"127.0.0.1",
"port":"1000"
}
},
複製代碼
配置好後,咱們在終端中輸入npm run dev,而後你會看到服務地址改成了127.0.0.1:1000.
在開發多頁項目時,都會定義一個全局的CSS來初始化咱們的頁面渲染,好比把padding和margin設置成0,網上也有很是出名的開源css文件normailze.css。要定義這些配置,須要在nuxt.config.js裏進行操做。
好比如今咱們要把頁面字體設置爲紅色,就能夠在assets/css/common.css文件,而後把字體設置爲紅色。
/assets/css/common.css
html{
color:red;
}
複製代碼
/nuxt.config.js
css:['~assets/css/normailze.css'],
複製代碼
設置好後,在終端輸入npm run dev 。而後你會發現字體已經變成了紅色。
在nuxt.config.js裏是能夠對webpack的基本配置進行覆蓋的,好比如今咱們要配置一個url-loader來進行小圖片的64位打包。就能夠在nuxt.config.js的build選項裏進行配置,相關可參照此連接www.cnblogs.com/ssh-007/p/7…
build: {
loaders:[
{
test:/\.(png|jpe?g|gif|svg)$/,
loader:"url-loader",
query:{
limit:10000,
name:'img/[name].[hash].[ext]'
}
}
],
/*
** Run ESLint on save
*/
extend (config, { isDev, isClient }) {
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}
複製代碼
nuxt.config.js文件中,修改title爲wfaceboss:
head: {
title: 'wfaceboss',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Nuxt.js project' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
複製代碼
修改後重啓服務,即運行 npm run dev,效果以下
Nuxt.js的路由並不複雜,它給咱們進行了封裝,讓咱們節省了不少配置環節。
Nuxt.js 依據 pages
目錄結構自動生成 vue-router 模塊的路由配置。
假設 pages
的目錄結構以下
└─pages
├─index.vue
└─user
├─index.vue
├─one.vue
複製代碼
那麼,Nuxt.js 自動生成的路由配置以下:
router: { routes: [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'user', path: '/user', component: 'pages/user/index.vue' }, { name: 'user-one', path: '/user/one', component: 'pages/user/one.vue' } ] } 複製代碼
<nuxt-link to="/users"></nuxt-link>
路由常常須要傳遞參數,咱們能夠簡單的使用params來進行傳遞參數,咱們如今向新聞頁面(news)傳遞個參數,而後在新聞頁面進行簡單的接收。
(1)使用nuxt傳遞參數
<template> <div> <ul> <li><nuxt-link :to="`informa/${item.newsCode}-${item.newsType}`"></li> </ul> </div> </template> 複製代碼
注意:name其實指向的是路由(文件夾或文件名),而路由死活區分大小寫的 , 因此to後面區分大小寫!!!建議文件夾都寫成小寫的。
(2)使用nuxt接收參數
async asyncData(context) { let newsCode = context.route.params.code.split('-')[0] let newsType = context.route.params.code.split('-')[1] }, 複製代碼
(3)使用this.$router.push的params傳遞參數
傳遞參數 -- this.$router.push({path: ' 路由 ', query: {key: value}})
參數取值 -- this.$route.query.key
注: 使用這種方式,傳遞參數會拼接在路由後面,出如今地址欄
複製代碼
(4)使用this.$router.push的params傳遞參數
傳遞參數 -- this.$router.push({name: ' 路由的name ', params: {key: value}}) 參數取值 -- this.$route.params.key 注: 使用這種方式,參數不會拼接在路由後面,地址欄上看不到參數 注意: 因爲動態路由也是傳遞params的,因此在 this.$router.push() 方法中 path不能和params一塊兒使用,不然params將無效。須要用name來指定頁面。 複製代碼
this.$route.query.key的方式參數顯示在地址欄上, 可是並非咱們想要的, :id?id=``?
因此建議仍是儘可能使用router-link來實現跳轉來解決地址欄的變化,更方便網站的優化
Nuxt.js 可讓你在動態路由對應的頁面組件中配置一個validate
方法用於校驗動態路由參數的有效性。該函數有一個布爾類型的返回值,若是返回true則表示校驗經過,若是返回false則表示校驗未經過。
export default { // nuxt中使用validate方法進行路由參數校驗,這個方法必須返回一個布爾值,爲true表示校驗經過,爲false表示校驗失敗。注意validate不能寫到methods屬性中。 validate(obj) { // console.log(obj); // return true return /^\d+$/.test(obj.params.id) } } 複製代碼
路由的動畫效果,也叫做頁面的更換效果。Nuxt.js提供兩種方法爲路由提供動畫效果,一種是全局的,一種是針對單獨頁面製做。
全局動畫默認使用page來進行設置,例如如今咱們爲每一個頁面都設置一個進入和退出時的漸隱漸現的效果。咱們能夠先在根目錄的assets/css下創建一個normailze.css文件。
(1)添加樣式文件
/assets/css/normailze.css(沒有請自行創建)
.page-enter-active, .page-leave-active {
transition: opacity 2s;
}
.page-enter, .page-leave-active {
opacity: 0;
}
複製代碼
(2)文件配置
而後在nuxt.config.js里加入一個全局的css文件就能夠了。
css:['assets/css/main.css'],
複製代碼
這時候在頁面切換的時候就會有2秒鐘的動畫切換效果了,可是你會發現一些頁面是沒有效果的,這是由於你沒有是<nuxt-link>
組件來製做跳轉連接。你須要進行更改。
好比咱們上節課做的動態路由新聞頁,你就須要改爲下面的連接。
<li><nuxt-link :to="{name:'news-id',params:{id:123}}">News-1</nuxt-link></li> 複製代碼
改過以後你就會看到動畫效果了。
想給一個頁面單獨設置特殊的效果時,咱們只要在css裏改變默認的page,而後在頁面組件的配置中加入transition字段便可。例如,咱們想給about頁面加入一個字體放大而後縮小的效果,其餘頁面沒有這個效果。
(1)在全局樣式assets/main.css 中添加如下內容
.test-enter-active, .test-leave-active {
transition: all 2s;
font-size:12px;
}
.test-enter, .test-leave-active {
opacity: 0;
font-size:40px;
}
複製代碼
(2)而後在about/index.vue組件中設置
export default {
transition:'test'
}
複製代碼
這時候就有了頁面的切換獨特動效了。
總結:在須要使用的頁面導入便可。
在開發應用時,常常會用到一些公用的元素,好比網頁的標題是同樣的,每一個頁面都是如出一轍的標題。這時候咱們有兩種方法,第一種方法是做一個公用的組件出來,第二種方法是修改默認模版。這兩種方法各有利弊,好比公用組件更加靈活,可是每次都須要本身手動引入;模版比較方便,可是隻能每一個頁面都引入。
Nuxt爲咱們提供了超簡單的默認模版訂製方法,只要在根目錄下建立一個app.html就能夠實現了。如今咱們但願每一個頁面的最上邊都加入「 學習nuxt.js」 這幾個字,咱們就可使用默認模版來完成。
app.html中:
<!DOCTYPE html> <html lang="en"> <head> {{ HEAD }} </head> <body> <p>學習nuxt.js</p> {{ APP }} </body> </html> 複製代碼
這裏的{{ HEAD }}讀取的是nuxt.config.js裏的信息,{{APP}} 就是咱們寫的pages文件夾下的主體頁面了。須要注意的是HEAD和APP都須要大寫,若是小寫會報錯的。
注意:若是你創建了默認模板後,記得要重啓服務器,不然顯示不會成功;可是默認佈局是不用重啓服務器的。
默認模板相似的功能還有默認佈局,可是從名字上你就能夠看出來,默認佈局主要針對於頁面的統一佈局使用。它在位置根目錄下的layouts/default.vue。須要注意的是在默認佈局裏不要加入頭部信息,只是關於<template>
標籤下的內容統一訂製。
需求:咱們在每一個頁面的最頂部放入「學習nuxt.js」 這幾個字,看一下在默認佈局裏的實現。
<template> <div> <p>學習nuxt.js</p> <nuxt/> </div> </template> 複製代碼
這裏的<nuxt/>
就至關於咱們每一個頁面的內容,你也能夠把一些通用樣式放入這個默認佈局裏,但會增長頁面的複雜程度。
總結:要區分默認模版和默認佈局的區別,模版能夠訂製不少頭部信息,包括IE版本的判斷;模版只能定製<template>
裏的內容,跟佈局有關係。在工做中修改時要看狀況來編寫代碼。
下載npm i element-ui -S
在plugins文件夾下面,建立ElementUI.js文件
import Vue from 'vue' import ElementUI from 'element-ui' Vue.use(ElementUI) 複製代碼
在nuxt.config.js中添加配置
css: [
'element-ui/lib/theme-chalk/index.css'
],
plugins: [
{src: '~/plugins/ElementUI', ssr: true }
],
build: {
vendor: ['element-ui']
}
複製代碼
npm install --save axios
import axios from 'axios' asyncData(context, callback) { axios.get('http://localhost:3301/in_theaters') .then(res => { console.log(res); callback(null, {list: res.data}) }) } 複製代碼
module.exports = {
build: {
vendor: ['axios']
}
}
複製代碼
當用戶輸入路由錯誤的時候,咱們須要給他一個明確的指引,因此說在應用程序開發中404頁面是必不可少的。Nuxt.js支持直接在默認佈局文件夾裏創建錯誤頁面。
在根目錄下的layouts文件夾下創建一個error.vue文件,它至關於一個顯示應用錯誤的組件。
<template> <div> <h2 v-if="error.statusCode==404">404頁面不存在</h2> <h2 v-else>500服務器錯誤</h2> <ul> <li><nuxt-link to="/">HOME</nuxt-link></li> </ul> </div> </template> <script> export default { props:['error'], } </script> 複製代碼
代碼用v-if進行判斷錯誤類型,須要注意的是這個錯誤是你須要在<script>
裏進行聲明的,若是不聲明程序是找不到error.statusCode的。
這裏我也用了一個<nuxt-link>
的簡單寫法直接跟上路徑就能夠了。
頁面的Meta對於SEO的設置很是重要,好比你如今要做個新聞頁面,那爲了搜索引擎對新聞的收錄,須要每一個頁面對新聞都有不一樣的title和meta設置。直接使用head方法來設置當前頁面的頭部信息就能夠了。咱們如今要把New-1這個頁面設置成個性的meta和title。
1.咱們先把pages/news/index.vue
頁面的連接進行修改一下,傳入一個title,目的是爲了在新聞具體頁面進行接收title,造成文章的標題。
/pages/news/index.vue
<li><nuxt-link :to="{name:'news-id',params:{id:123,title:'nuxt.com'}}">News-1</nuxt-link></li> 複製代碼
2.第一步完成後,咱們修改/pages/news/_id.vue,讓它根據傳遞值變成獨特的meta和title標籤。
<template> <div> <h2>News-Content [{{$route.params.id}}]</h2> <ul> <li><a href="/">Home</a></li> </ul> </div> </template> <script> export default { validate ({ params }) { // Must be a number return /^\d+$/.test(params.id) }, data(){ return{ title:this.$route.params.title, } }, //獨立設置head信息 head(){ return{ title:this.title, meta:[ {hid:'description',name:'news',content:'This is news page'} ] } } } </script> 複製代碼
注意:爲了不子組件中的meta標籤不能正確覆蓋父組件中相同的標籤而產生重複的現象,建議利用 hid 鍵爲meta標籤配一個惟一的標識編號。
Nuxt.js貼心的爲咱們擴展了Vue.js的方法,增長了anyncData,異步請求數據。
(1)建立遠程數據
在這裏製做一些假的遠程數據,我選擇的網站是myjson.com,它是一個json的簡單倉庫,學習使用是很是適合的。 咱們打開網站,在對話空中輸入JSON代碼,這個代碼能夠隨意輸入,key和value均採用字符串格式建立。
{
"name": "Nuxt",
"age": 18,
"interest": "I love coding!"
}
複製代碼
輸入後保存,網站會給你一個地址,這就是你這個JSON倉庫的地址了。api.myjson.com/bins/1ctwlm
(2)安裝Axios
Vue.js官方推薦使用的遠程數據獲取方式就Axios,因此咱們安裝官方推薦,來使用Axios。這裏咱們使用npm 來安裝 axios。 直接在終端中輸入下面的命令:
npm install axios --save
複製代碼
咱們在pages下面新建一個文件,叫作ansyData.vue。而後寫入下面的代碼:
<script> import axios from 'axios' export default { data(){ return { name:'hello World', } }, asyncData(){ return axios.get('https://api.myjson.com/bins/1ctwlm') .then((res)=>{ console.log(res) return {info:res.data} }) } } </script> 複製代碼
這時候咱們能夠看到,瀏覽器中已經能輸出結果了。asyncData的方法會把值返回到data中。是組件建立(頁面渲染)以前的動做,因此不能使用this.info,
必定要return出去獲取到的對象,這樣就能夠在組件中使用,這裏返回的數據會和組件中的data合併。這個函數不光在服務端會執行,在客戶端一樣也會執行。 複製代碼
async asyncData(context) { let [newDetailRes, hotInformationRes, correlationRes] = await Promise.all([ axios.post('http://www.huanjingwuyou.com/eia/news/detail', { newsCode: newsCode }), axios.post('http://www.huanjingwuyou.com/eia/news/select', { newsType: newsType, // 資訊類型: 3環評資訊 4環評知識 start: 0, // 從第0條開始 pageSize: 10, newsRecommend: true }), axios.post('http://www.huanjingwuyou.com/eia/news/select', { newsType: newsType, // 資訊類型: 3環評資訊 4環評知識 start: 0, // 從第0條開始 pageSize: 3, newsRecommend: false }) ]) return { newDetailList: newDetailRes.data.result, hotNewList: hotInformationRes.data.result.data, newsList: correlationRes.data.result.data, newsCode: newsCode, newsType: newsType } }, 複製代碼
固然上面的方法稍顯過期,如今都在用ansyc…await來解決異步,改寫上面的代碼。
<script> import axios from 'axios' export default { data(){ return { name:'hello World', } }, async asyncData(){ let {data}=await axios.get('https://api.myjson.com/bins/8gdmr') return {info: data} } } </script> 複製代碼
this
來引用組件的實例對象(1)直接引入圖片 在網上任意下載一個圖片,放到項目中的static文件夾下面,而後可使用下面的引入方法進行引用 <div><img src="~static/logo.png" /></div> 複製代碼
「~」就至關於定位到了項目根目錄,這時候圖片路徑就不會出現錯誤,就算打包也是正常的。
(2)CSS引入圖片
若是在CSS中引入圖片,方法和html中直接引入是同樣的,也是用「~」符號引入。
複製代碼
<style> .diss{ width: 300px; height: 100px; background-image: url('~static/logo.png') } </style> 複製代碼
這時候在npm run dev 下是徹底正常的。
用Nuxt.js製做完成後,你能夠打包成靜態文件並放在服務器上,進行運行。
在終端中輸入:
npm run generate
複製代碼
而後在dist文件夾下輸入live-server就能夠了。
總結:Nuxt.js框架很是簡單,由於大部分的事情他都爲咱們作好了,咱們只要安裝它的規則來編寫代碼。
安裝axios
npm install @nuxtjs/axios --save-dev
複製代碼
安裝完成後更改配置信息:
nuxt.config.js
module.exports = { modules: [ // Doc: https://axios.nuxtjs.org/usage '@nuxtjs/axios', ], axios: { proxy:true // 代理 }, axios: { proxy: true, prefix: '/api', // baseURL credentials: true, }, proxy: { "/eia/":"http://192.168.0.97:8181/", // key(路由前綴):value(代理地址) changeOrigin: true, // 是否跨域 pathRewrite: { '^/api': '' //路徑重寫 } } } 複製代碼
既然說到了axios
,就不得不提到的一個東西就是攔截器,非常有用在項目開發過程當中必不可少的。
舉個例子:
安裝
npm install @nuxtjs/axios @nuxtjs/proxy --save
複製代碼
module.expores{ plugins: [ { src: "~/plugins/axios", ssr: false }, ], 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') } }) } export default function (app) { let axios = app.$axios; // 基本配置 axios.defaults.timeout = 10000 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' // 請求回調 axios.onRequest(config => {}) // 返回回調 axios.onResponse(res => {}) // 錯誤回調 axios.onError(error => {}) } 複製代碼
緣由: asyncData方法異步請求數據時,覺得/api/${params.id}這個接口的網址是 127.0.0.1:80, 因此將請求發送給了127.0.0.1:80,而個人接口服務器並無跑在80端口上,因此報錯。
解決方法:
export default { asyncData ({ params }) { return axios.get(`https://127.0.0.1:3000/api/${params.id}`) .then((res) => { return { title: res.data.title } }) } } 複製代碼
背景: 在
<head>
標籤中,以inline的形式引入flexible.js
文件。本項目主要爲移動端項目,引入flexible.js
實現移動端適配問題。
Nuxt.js 經過 vue-meta
實現頭部標籤管理,經過查看文檔發現,能夠按照以下方式配置:
head: { script: [{ innerHTML: require('./assets/js/flexible'), type: 'text/javascript', charset: 'utf-8'}], __dangerouslyDisableSanitizers: ['script'] } 複製代碼
背景:在組件中的
<template>
,<script>
或<style>
上使用各類預處理器,加上處理器後,控制檯報錯。
npm install --save-dev node-sass sass-loader
複製代碼
可是解決過程並非很順利的,在閱讀中文文檔時,忽略版本號,按照上面的提示進行操做,發現不能成功,後來各類debug,最後發現了該解決方案。後知後覺的發現了中文文檔的版本號太低,若是須要查看文檔,必定要看最新版本的英文文檔!
背景:在css中,寫入px,經過
px2rem loader
,將px轉換成rem
在之前的項目中,是經過 px2rem loader
實現的,可是在Nuxt.js項目下,添加 css loader 仍是很費力的,由於涉及到vue-loader
。
想到了一個其餘方案,可使用 postcss
處理。能夠在 nuxt.config.js
文件中添加配置,也能夠在postcss.conf.js
文件中添加。
build: { postcss: [ require('postcss-px2rem')({ remUnit: 75 // 轉換基本單位 }) ] }, 複製代碼
背景:給 utils 目錄添加別名
剛剛說到,Nuxt.js內置了 webpack
配置,若是想要拓展配置,能夠在 nuxt.config.js
文件中添加。同時也能夠在該文件中,將配置信息打印出來。
extend (config, ctx) { console.log('webpack config:', config) if (ctx.isClient) { // 添加 alias 配置 Object.assign(config.resolve.alias, { 'utils': path.resolve(__dirname, 'utils') }) } } 複製代碼
背景:本身封裝了一個 toast vue plugin,因爲 vue 實例化的過程沒有暴露出來,不知道在哪一個時機注入進去。
能夠在 nuxt.config.js
中添加 plugins 配置,這樣插件就會在 Nuxt.js 應用初始化以前被加載導入。
module.exports = { plugins: ['~plugins/toast'] } 複製代碼
~plugins/toast.js 文件:
import Vue from 'vue' import toast from '../utils/toast' import '../assets/css/toast.css' Vue.use(toast) 複製代碼
背景:在項目中,設置 3個
NODE_ENV
的值,來對應不一樣的版本。development,本地開發;release,預發佈版本;production,線上版本。其中,預發佈版本比production版本,多出vconsole。
// package.json "scripts": { "buildDev": "cross-env NODE_ENV=release nuxt build && backpack build", "startDev": "cross-env NODE_ENV=release PORT=3000 node build/main.js" }, 複製代碼
打印 process.env.NODE_ENV
依舊是,production
。
在 backpack 的源碼中,找到了答案,在 執行 backpack build
命令時,會把 process.env.NODE_ENV
修改成 production
,而且是寫死的不可配置的......
無奈下,只能在 process.env
下,添加 __ENV
屬性,表明 NODE_ENV
這時,在頁面中打印出來的信息 process.env.__ENV undefined
,可是能夠打印出 process.env.NODE_ENV
。
能夠經過配置 nuxt.config.js
中的,env
屬性,解決該問題。
env: {
__ENV: process.env.__ENV
}
複製代碼
背景: 在引入第三方插件,或者直接在代碼中寫
window
時,控制檯會給出警告,window
未定義。
發生在這個問題的緣由時,node服務端並無window
或 document
對象。解決方法,經過 process.browser
來區分環境。
if (process.browser) { // 引入第三方插件 require('***') // 或者修改window對象下某一屬性 window.mbk = {} } 複製代碼
例如使用UI框架:element-ui
我找了不少相關文章,並無詳細說明該如何引入。因此我要拿出來將他說明:
先來看下,若是不按需引入vendor.js
的體積大小爲:
第一步,下載依賴:
# 先下載element-ui npm install element-ui --save # 若是使用按需引入,必須安裝babel-plugin-component(官網有須要下載說明,此插件根據官網規則不一樣,安裝插件不一樣) npm install babel-plugin-component --save-dev 複製代碼
安裝好之後,按照nuxt.js
中的規則,你須要在 plugins/
目錄下建立相應的插件文件
在文件根目錄建立(或已經存在)plugins/
目錄,建立名爲:element-ui.js
的文件,內容以下:
import Vue from 'vue' import { Button } from 'element-ui' //引入Button按鈕 export default ()=>{ Vue.use(Button) } 複製代碼
第二步,引入插件
在nuxt.config.js
中,添加配置爲:plugins
css:[ 'element-ui/lib/theme-chalk/index.css' ], plugins:[ '~/plugins/element-ui' ] 複製代碼
默認爲:開啓SSR,採用服務端渲染,也能夠手動配置關閉SSR,配置爲:
css:[ 'element-ui/lib/theme-chalk/index.css' ], plugins:[ { src:'~/plugins/element-ui', ssr:false //關閉ssr } ] 複製代碼
第三步,配置
babel
選項
在nuxt.config.js
中,配置在build
選項中,規則爲官網規則:
build: { babel:{ //配置按需引入規則 "plugins":[ [ "component", { "libraryName":"element-ui", "styleLibraryName":"theme-chalk" } ] ] }, /* ** Run ESLINT on save */ extend (config, ctx) { if (ctx.isClient) { config.module.rules.push({ enforce: 'pre', test: /\.(js|vue)$/, loader: 'eslint-loader', exclude: /(node_modules)/ }) } } } 複製代碼
此時,咱們在觀察打包之後文件體積大小,如圖:
此時,咱們成功完成了按需引入配置。
(1) <no-ssr> 插件或者組件 </no-ssr> (2) nuxt.config.js裏ssr改成false plugins: [ {src: '~/plugins/ElementUI', ssr: false } ], 複製代碼
解決: 可使用axios的baseURL來代理
import Vue from 'vue' import axios from 'axios' // axios.defaults.baseURL = "http://www.huanjingwuyou.com/" axios.defaults.baseURL = "http://localhost:3000/" // axios.defaults.baseURL = "http://test.huanjingwuyou.com/" export default axios 複製代碼
nuxt是沒有index.html頁面的, 我們應該在哪裏寫js代碼來判斷設備呢, 下面請看個人代碼吧
nuxt.config.js
裏經過router
來引入middleware
中間件nuxt.config.js
代碼以下
export default { router: { middleware: ["device"], }, } 複製代碼
utils
文件而且新建文件deviceType.js
deviceType.js
文件代碼以下
/** * * @param {*} UA ,就是userAgent * @returns type: 設備類型 * env: 訪問環境(微信/微博/qq) * masklayer: 就是給外部拿到判斷是否顯示遮罩層的,一些特殊環境要引導用戶到外部去打開訪問 */ function isWechat(UA) { return /MicroMessenger/i.test(UA) ? true : false; } function isWeibo(UA) { return /Weibo/i.test(UA) ? true : false; } function isQQ(UA) { return /QQ/i.test(UA) ? true : false; } function isMoible(UA) { return /(Android|webOS|iPhone|iPod|tablet|BlackBerry|Mobile)/i.test(UA) ? true : false; } function isIOS(UA) { return /iPhone|iPad|iPod/i.test(UA) ? true : false; } function isAndroid(UA) { return /Android/i.test(UA) ? true : false; } export function deviceType(UA) { if (isMoible(UA)) { if (isIOS(UA)) { if (isWechat(UA)) { return { type: "ios", env: "wechat", masklayer: true, }; } if (isWeibo(UA)) { return { type: "ios", env: "weibo", masklayer: true, }; } if (isQQ(UA)) { return { type: "ios", env: "qq", masklayer: true, }; } return { type: "ios", }; } if (isAndroid(UA)) { if (isWechat(UA)) { return { type: "android", env: "wechat", masklayer: true, }; } if (isWeibo(UA)) { return { type: "android", env: "weibo", masklayer: true, }; } if (isQQ(UA)) { return { type: "android", env: "qq", masklayer: true, }; } return { type: "android", }; } return { type: "mobile", }; } else { return { type: "pc", }; } } 複製代碼
middleware
裏添加device.js
文件device.js
代碼以下
// @ts-nocheck import { deviceType } from "~/utils/deviceType"; export default function(context) { // @ts-ignore context.userAgent = process.server ? context.req.headers["user-agent"] : navigator.userAgent; // 給全局上下文添加一個屬性來保存咱們返回的匹配信息 context.deviceType = deviceType(context.userAgent); // 這裏注入到store,是由於我部分頁面須要判斷機型請求不一樣的數據, // 大家沒有用到的話能夠移除 // context.store.commit("SetDeviceType", context.deviceType); // 如果判斷UA非移動端的,就在這裏作處理了.. // context.redirect(status,url) 這個能夠重定向到外部網站 // 如果內部訪問能夠直接用router對象push if (context.deviceType.type === "pc") { // context.redirect(302,'www.huanjingwuyou.com') //301是永久重定向,若是你想隨着設備類型改變一直變,請改成302 } else { context.redirect(302,'m.huanjingwuyou.com') //301是永久重定向,若是你想隨着設備類型改變一直變,請改成302 } } 複製代碼
asyncData
方法會在組件(限於頁面組件)每次會在刷新加載頁面或者切換路由時被調用,順序比beforeCreate和created以前訪問域名
, 能夠經過axios配置axios.defaults.baseURL
.nuxt
, assets
, package.json
, nuxt.config.js
, static
放到Nginx裏進行代理若是組件不是和路由綁定的頁面組件,原則上是不可使用異步數據的。由於 Nuxt.js 僅僅擴展加強了頁面組件的 data
方法,使得其能夠支持異步數據處理。
對於非頁面組件,有兩種方式能夠實現數據的異步獲取:
mounted
方法裏面實現異步獲取數據的邏輯,以後設置組件的數據,限制是:不支持服務端渲染。asyncData
或fetch
方法中進行API調用,並將數據做爲props
傳遞給子組件。服務器渲染工做正常。缺點:asyncData
或頁面提取可能不太可讀,由於它正在加載其餘組件的數據。 總之,使用哪一種方法取決於你的應用是否須要支持子組件的服務端渲染。這是由於在開發模式下,爲了經過 Webpack 實現熱加載,CSS代碼是打包在 JavaScript 代碼中,並動態打到頁面中去,從而元素重繪引發了閃爍。
不用擔憂,在生產模式下,CSS代碼會單獨打包至獨立的文件並置於head標籤內,不會出現頁面閃爍的現象。
做爲命令參數直接傳遞
nuxt --hostname myhost --port 3333
複製代碼
或
"scripts": { "dev": "nuxt --hostname myhost --port 3333" } 複製代碼
在 nuxt.config.js
中配置:
在 nuxt.config.js
添加:
export default { server: { port: 8000, // default: 3000 host: '0.0.0.0', // default: localhost }, // other configs } 複製代碼
使用 NUXT_HOST 和 NUXT_PORT env 變量
與 HOST 和 PORT 相似,但更具體,以防您須要添加其餘東西。
"scripts": { "dev": "NUXT_HOST=0.0.0.0 NUXT_PORT=3333 nuxt" } 複製代碼
注意: 爲了更好的跨平臺開發支持,您可使用 cross-env 依賴包。
安裝依賴:
npm install --save-dev cross-env
複製代碼
配置cross-env:
"scripts": { "dev": "cross-env NUXT_HOST=0.0.0.0 NUXT_PORT=3333 nuxt" } 複製代碼
使用HOST和PORT env變量
"scripts": { "dev": "HOST=0.0.0.0 PORT=3333 nuxt" } 複製代碼
在 package.json
中配置 nuxt
:
在您的 package.json
文件中添加:
"config": { "nuxt": { "host": "0.0.0.0", "port": "3333" } }, "scripts": { "dev": "nuxt" } 複製代碼