天天看點

Nuxt.jsStudy NotesNuxt.js

Study Notes

Nuxt.js

介紹

Nuxt.js 是什麼?

Nuxt.js 是一個基于 Vue.js 的通用應用架構。

通過對用戶端/服務端基礎架構的抽象組織,Nuxt.js 主要關注的是應用的 UI 渲染。

我們的目标是建立一個靈活的應用架構,你可以基于它初始化新項目的基礎結構代碼,或者在已有 Node.js 項目中使用 Nuxt.js。

Nuxt.js 預設了利用 Vue.js 開發服務端渲染的應用所需要的各種配置。

除此之外,我們還提供了一種指令叫:

nuxt generate

,為基于 Vue.js 的應用提供生成對應的靜态站點的功能。

我們相信這個指令所提供的功能,是向開發內建各種微服務(Microservices)的 Web 應用邁開的新一步。

作為架構,Nuxt.js 為

用戶端/服務端

這種典型的應用架構模式提供了許多有用的特性,例如異步資料加載、中間件支援、布局支援等。

Nuxt.js 架構是如何運作的?

Nuxt.jsStudy NotesNuxt.js
  • Vue.js
  • Vue-Router
  • Vuex (當配置了 Vuex 狀态樹配置項 時才會引入)
  • Vue 伺服器端渲染 (排除使用 mode: ‘spa’)
  • Vue-Meta
壓縮并 gzip 後,總代碼大小為:57kb (如果使用了 Vuex 特性的話為 60kb)。
另外,Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 來處理代碼的自動化建構工作(如打包、代碼分層、壓縮等等)。

特性

  • 基于 Vue.js
    • Vue、Vue Router、Vuex、Vue SSR
  • 自動代碼分層
  • 服務端渲染
  • 強大的路由功能,支援異步資料
  • 靜态檔案服務
  • ES2015+ 文法支援
  • 打包和壓縮 JS 和 CSS
  • HTML 頭部标簽管理
  • 本地開發支援熱加載
  • 內建 ESLint
  • 支援各種樣式預處理器: SASS、LESS、 Stylus 等等
  • 支援 HTTP/2 推送

建立項目

Nuxt 提供了兩種方式用來建立項目:

  • 使用 create-nuxt-app 腳手架工具
  • 手動建立

這裡介紹手動建立 Nuxt 項目

準備工作

// 建立項目檔案夾
mkdir nuxtjs-demo

// 進入項目檔案夾
cd nuxtjs-demo

// 初始化 package.json
yarn init -y
// 或者
npm init -y

// 安裝 nuxt
yarn add nuxt -D
// 或者
npm i nuxt -D
           

配置 nuxt 運作腳本

package.json

{
  "name": "nuxtjs-demo",
  "scripts": {
    "dev": "nuxt"
  },
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "nuxt": "^2.14.3"
  }
}
           

上面的配置使得我們可以通過運作

npm run dev

或者

yarn dev

來運作 nuxt。

建立 vue 頁面并啟動項目

Nuxt.js 會依據 pages 目錄中的所有 *.vue 檔案生成應用的路由配置。

// 建立pages 檔案夾
mkdir pages
           

建立

pages/index.vue

<template>
  <div class="home">
    <h2>hello nuxt.js</h2>
  </div>
</template>
           

啟動項目

npm run dev
// 或者
yarn dev
           
第一次啟動項目,其會詢問你是否加入他們,直接

N

就行了
注意:Nuxt.js 會監聽 pages 目錄中的檔案更改,是以在添加新頁面時無需重新啟動應用程式。

router

基本使用

Nuxt.js 依據

pages

目錄結構自動生成

vue-router

子產品的路由配置。

要在頁面之間使用路由,我們建議使用

<nuxt-link>

标簽。

pages 目錄結構

Nuxt.jsStudy NotesNuxt.js

生成對應的 vue-router 配置

  • .nuxt/router.js
import Vue from 'vue';
import Router from 'vue-router';
import { interopDefault } from './utils';
import scrollBehavior from './router.scrollBehavior.js';

const _6f480cd4 = () =>
  interopDefault(
    import(
      '..\\pages\\about\\index.vue' /* webpackChunkName: "pages/about/index" */
    ),
  );
const _9b58e274 = () =>
  interopDefault(
    import(
      '..\\pages\\user\\index.vue' /* webpackChunkName: "pages/user/index" */
    ),
  );
const _f046dd4c = () =>
  interopDefault(
    import('..\\pages\\user\\one.vue' /* webpackChunkName: "pages/user/one" */),
  );
const _2585f79e = () =>
  interopDefault(
    import('..\\pages\\index.vue' /* webpackChunkName: "pages/index" */),
  );

// TODO: remove in Nuxt 3
const emptyFn = () => {};
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location, onComplete = emptyFn, onAbort) {
  return originalPush.call(this, location, onComplete, onAbort);
};

Vue.use(Router);

export const routerOptions = {
  mode: 'history',
  base: decodeURI('/'),
  linkActiveClass: 'nuxt-link-active',
  linkExactActiveClass: 'nuxt-link-exact-active',
  scrollBehavior,

  routes: [
    {
      path: '/about',
      component: _6f480cd4,
      name: 'about',
    },
    {
      path: '/user',
      component: _9b58e274,
      name: 'user',
    },
    {
      path: '/user/one',
      component: _f046dd4c,
      name: 'user-one',
    },
    {
      path: '/',
      component: _2585f79e,
      name: 'index',
    },
  ],

  fallback: false,
};

export function createRouter() {
  return new Router(routerOptions);
}
           

路由導航

使用基本與 vue-router 一緻

a 标簽

<template>
  <!--會重新整理頁面,走服務端渲染-->
  <a href="/" target="_blank" rel="external nofollow" >home</a>
</template>
           

<nuxt-link>

元件

<template>
  <!--  nuxt.js的路由元件,使用與router-link基本一緻-->
  <nuxt-link to="/">home</nuxt-link>
</template>
           

程式設計式導航

<template>
  <button @click="$router.push('/')">home</button>
</template>
           

動态路由

Nuxt.js

裡面定義帶參數的動态路由,需要建立對應的以下劃線作為字首的 Vue 檔案 或 目錄。

以下目錄結構:

pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue
           

Nuxt.js 生成對應的路由配置表為:

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue',
    },
    {
      name: 'users-id',
      path: '/users/:id?',
      component: 'pages/users/_id.vue',
    },
    {
      name: 'slug',
      path: '/:slug',
      component: 'pages/_slug/index.vue',
    },
    {
      name: 'slug-comments',
      path: '/:slug/comments',
      component: 'pages/_slug/comments.vue',
    },
  ];
}
           

你會發現名稱為users-id的路由路徑帶有:id?參數,表示該路由是可選的。如果你想将它設定為必選的路由,需要在users/_id目錄内建立一個index.vue檔案。

generate 指令會忽略動态路由: API Configuration generate

嵌套路由

你可以通過 vue-router 的子路由建立 Nuxt.js 應用的嵌套路由。

建立内嵌子路由,你需要添加一個 Vue 檔案,同時添加一個與該檔案同名的目錄用來存放子視圖元件。

别忘了在父元件(.vue檔案) 内增加

<nuxt-child/>

用于顯示子視圖内容。

假設檔案結構如:

pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue
           

Nuxt.js 自動生成的路由配置如下:

router: {
  routes: [
    {
      path: '/users',
      component: 'pages/users.vue',
      children: [
        {
          path: '',
          component: 'pages/users/index.vue',
          name: 'users',
        },
        {
          path: ':id',
          component: 'pages/users/_id.vue',
          name: 'users-id',
        },
      ],
    },
  ];
}
           

路由配置

視圖

Nuxt.jsStudy NotesNuxt.js

模闆

你可以定制化 Nuxt.js 預設的應用模闆。

定制化預設的 html 模闆,隻需要在 src 檔案夾下(預設是應用根目錄)建立一個app.html的檔案。

布局

Nuxt.js 允許你擴充預設的布局,或在layout目錄下建立自定義的布局。

  • 預設布局

    可通過添加layouts/default.vue檔案來擴充應用的預設布局。

  • 自定義布局

    layouts目錄中的每個檔案 (頂級) 都将建立一個可通過頁面元件中的layout屬性通路的自定義布局。

頁面(pages 裡的)

頁面元件實際上是 Vue 元件,隻不過 Nuxt.js 為這些元件添加了一些特殊的配置項(對應 Nuxt.js 提供的功能特性)以便你能快速開發通用應用。

HTML 頭部

  • 預設 Meta 标簽
  • 個性化特定頁面的 Meta 标簽

異步資料

Nuxt.js 擴充了 Vue.js,增加了一個叫asyncData的方法,使得我們可以在設定元件的資料之前能異步擷取或處理資料。

asyncData

asyncData 方法會在元件(限于頁面元件)每次加載之前被調用。它可以在服務端或路由更新之前被調用。在這個方法被調用的時候,第一個參數被設定為目前頁面的上下文對象,你可以利用 asyncData 方法來擷取資料,Nuxt.js 會将 asyncData 傳回的資料融合元件 data 方法傳回的資料一并傳回給目前元件。

由于 asyncData 方法是在元件 初始化 前被調用的,是以在方法内是沒有辦法通過 this 來引用元件的執行個體對象。

上下文對象(用于 asyncData 方法)

可通過 API context 來了解該對象的所有屬性和方法。

錯誤處理

Nuxt.js 在上下文對象context中提供了一個error(params)方法,你可以通過調用該方法來顯示錯誤資訊頁面。params.statusCode可用于指定服務端傳回的請求狀态碼。

生命周期

鈎子函數 說明 Server Client
beforeCreate 在執行個體建立之前被調用,此時還拿不到資料和 DOM。
created 在執行個體建立完成後被調用,此時可以操作資料了。
beforeMount 在挂載開始之前被調用:相關的 render 函數首次被調用。
mounted 執行個體被挂載後調用,此時可以執行一些初始 DOM 操作。
beforeUpdate 資料更新時調用,發生在虛拟 DOM 打更新檔之前。這裡适合在更新之前通路現有的 DOM,比如手動移除已添加的事件監聽器。
updated 由于資料更改導緻的虛拟 DOM 重新渲染和打更新檔,在這之後會調用該鈎子。當這個鈎子被調用時,元件 DOM 已經更新,是以你現在可以執行依賴于 DOM 的操作。
activated 被 keep-alive 緩存的元件激活時調用。
deactivated 被 keep-alive 緩存的元件停用時調用。
beforeDestroy 執行個體銷毀之前調用。在這一步,執行個體仍然完全可用。
destroyed 執行個體銷毀後調用。該鈎子被調用後,對應 Vue 執行個體的所有指令都被解綁,所有的事件監聽器被移除,所有的子執行個體也都被銷毀。
errorCaptured 當捕獲一個來自子孫元件的錯誤時被調用。

Nuxt 渲染流程

下圖闡述了 Nuxt.js 應用一個完整的伺服器請求到渲染(或使用者通過

<nuxt-link>

切換路由渲染頁面)的流程:

Nuxt.jsStudy NotesNuxt.js

Nuxt 常見問題

官方 demo

下一篇——搭建自己的 SSR