Skip to content

Vue2项目资料:Nuxt 学习笔记

Nuxt.js(后文Nuxt)是基于Vue.js的通用应用框架

通过对客户端/服务端基础架构的抽象组织,Nuxt主要关注的是应用的UI渲染。其预设了利用Vue开发服务端渲染的应用所需要的各种配置。 作为框架,Nuxt.js 为 客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。

基本介绍

如何运作

vue2+ vue-router vuex vue-meta 以及webpack、vue-loader、babel-loader来处理代码的自动化构建工作

特性

  • 基于Vue
  • 自动代码分层
  • 服务端渲染
  • 强大的路由功能,支持异步数据
  • 静态服务文件
  • ES6+语法支持
  • 打包和压缩JS/CSS
  • HTML头部标签管理
  • 本地开发支持热加载
  • 集成ESLint
  • 支持样式预处理

下图阐述了 Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 <nuxt-link> 切换路由渲染页面)的流程:

<img src="https://zh.nuxtjs.org/nuxt-schema.png">

请求到来 -> nuxt server拦截处理(事件派发store action) -> middleware处理中间件 (先配置,后布局,再页面) -> 验证 -> 获取异步数据 -> render渲染(通过Navigate作路由跳转)

服务端渲染

使用nuxt作UI渲染框架。当运行nuxt命令时会启动一个支持热加载服务端渲染(基于Vue的vue-server-renderer模块)的开发服务器。

静态化

nuxt generate

通过CDN缓存静态页面,进行全球CDN节点布局。相对传统的动态网站,静态化分散了对服务器的请求,降低服务器压力。

简而言之,页面静态文件CDN,数据通过API,前后端分离.

demo

安装

vue init nuxt-community/starter-template nuxt-demo

要注意,服务端渲染是前台服务端用相同组件,一份代码,我们跑的其实是静态文件,所以需要打包出来一份bundle

npm run build

npm run dev

现在浏览器打开 localhost:3000 就可以访问nuxt-demo了

目录结构

  • assets 组织静态资源 css js等

  • components 放公共组件。注:nuxt不会扩展该目录下的组件,所以不会有asyncData特性

  • layouts 用于组织布局,除配置外这个优先级很高

  • middleware 存放中间件

  • pages 组织页面及路由,在layouts后读取,配置这个就不用写routes了. 后面介绍很爽

  • plugins 插件,用于组织需要在根vue.js实例化之前运行的JS插件

  • static 静态文件目录,不会被nuxt调用构建。服务启动,该目录下文件会被映射到根路径下

  • store Vuex状态文件

  • nuxt.config.js nuxt配置,优先级最高,用于覆盖默认配置

更多请参考官方文档 https://zh.nuxtjs.org ~

路由

Nuxt根据pages目录结构自动生成vue-router模块路由配置,就问你叼不叼~

在pages下新建一个user文件夹,新建index.vue one.vue

访问 localhost:3000/user localhost:3000/user/one 就能显示了,简直不要太爽

动态路由

以前path里配置 /:id 这样的,在pages/user 里新建 _id.vue即可

路由参数校验

pages/users/_id.vue

js
export default {
  validate({params}) {
    return /^\d+$/.test(params.id)
  }
}

嵌套路由

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

过渡动效

参考文档 - - 我没跑成功,回头再看看

中间件

允许定义一个自定义函数运行在一个页面或一组页面渲染之前。放在middleware目录下,一个中间件接收context作为第一个参数:

js
export default function(context) {
  context.userAgent = context.isServer 
    ? context.req.headers['user-agent']
    : navigator.userAgent
}

中间件执行顺序:

  1. nuxt.config.js
  2. 匹配布局
  3. 匹配页面

中间件可异步执行,只需返回一个Promise或使用第二个callback作为第一个参数:

middleware/stats.js

js
import axios from 'axios'

export default function({route}) {
  return axios.post('http://xx.com', {
    url: route.fullPath
  })
}

然后在 上面3个任意地方使用中间件:

js
module.exports = {
  router: {
    middleware: 'stats'
  }
}

stats中间件将在每个路由改变时被调用。

视图

默认页面

layouts/default.vue

错误页面

layouts/error.vue

个性化布局

在layouts里添加一个dark.vue文件,然后在pages里的组件写.

js
export default {
  layout: 'dark'
}

页面

页面的一些api

属性名描述
asyncData最重要的一个键, 支持 异步数据处理,另外该方法的第一个参数为当前页面组件的 上下文对象
fetch与 asyncData 方法类似,用于在渲染页面之前获取数据填充应用的状态树(store)。不同的是 fetch 方法不会设置组件的数据。详情请参考 关于fetch方法的文档
head配置当前页面的 Meta 标签, 详情参考 页面头部配置API
layout指定当前页面使用的布局(layouts 根目录下的布局文件)。详情请参考 关于 布局 的文档
transition指定当前页面使用的布局(layouts 根目录下的布局文件)。详情请参考 关于 布局 的文档
scrollToTop布尔值,默认: false。 用于判定渲染页面前是否需要将当前页面滚动至顶部。这个配置用于 嵌套路由的应用场景
middleware指定页面的中间件,中间件会在页面渲染之前被调用, 请参考 路由中间件

HTML头部

nuxt使用vue-meta更新应用头部标签和html属性

js
{
  keyName: 'head', // 设置meta信息的组件对象的字段,vue-meta会根据key值获取meta信息
  attribute: 'n-head', // vue-meta在监听标签时所添加的属性名
  ssrAttribute: 'n-head-ssr', // 让vue-meta获知meta信息已完成服务端渲染的属性名
  tagIDKeyName: 'hid' // 让vue-meta用来决定是否覆盖还是追加tag的属性名
}

异步数据

Nuxt扩展了Vue增加一个asyncData方法,使得我们可以在设置组件数据前异步获取处理数据

asyncData

该方法会在组件(限于页面组件)每次加载前被调用。它可以在服务端或路由更新之前被调用。在该方法被调用时,第一个参数被设定为当前页面的上下文对象,可利用asyncData方法来获取数据,Nuxt会将asyncData返回的数据融合组件data方法返回的数据一并返回给当前组件。

由于asyncData方法是在组件初始化前被调用的,所以在方法内是无法通过this来引用组件实例对象的。

使用:

  1. 返回Promise
js
asyncData({params, error}) {
  return axios.get(`/api/${params.id}`)
    .then(res => {
      return {title: res.data.title}
    })
    .catch(err => {
      error({ statusCode: 404, message: 'not found' })
    })
}
  1. 使用async/await
js
asyncData({params, error}) {
  try {
    let {data} = await axios.get(`/api/${params.id}`)
    return {title: data.title}
  } catch (err) {
    error({ statusCode: 404, message: 'not found' })
  }
}

资源文件

默认Nuxt使用vue-loader、file-loader及url-loader来处理文件的加载和引用。对于不需要通过webpack处理的静态资源文件,可以放置在static目录中

webpack构建

默认情况下, vue-loader自动使用 css-loader 和Vue模板编译器来编译处理vue文件中的样式和模板。在此编译过程中,所有的资源URL例如 &lt;img src="...">background: url(...) 和 CSS中的 @import 均会被解析成模块通过 require 引用。

静态文件

如果你的静态资源文件需要 Webpack 做构建编译处理,可以放到 assets 目录,否则可以放到 static 目录中去。

Nuxt 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下,像 robots.txt 或 sitemap.xml 这种类型的文件就很适合放到 static 目录中。

你可以在代码中使用根路径 / 结合资源相对路径来引用静态资源:

html
&lt;!-- 引用 static 目录下的图片 -->
&lt;img src="/my-image.png"/>

&lt;!-- 引用 assets 目录下经过 webpack 构建处理后的图片 -->
&lt;img src="/assets/my-image-2.png"/>

插件

使用第三方模块

在页面内直接 import。但是,如果在另一页面也import相同第三方模块,在打包时该模块会被重复打包,而实际上我们只需要打包一次。该问题可以通过在nuxt.config.js里配置build.vendor来解决:

js
module.exports = {
  build: {
    vendor: ['axios']
  }
}

使用Vue插件

plugins里增加相应插件的js文件,如xxx.js

js
module.exports = {
  plugins: [
    // '~/plugins/xxx',
    {
      src: '~/plugins/xxx',
      ssr: false
    }
    // 有些插件可能只是在浏览器里使用,所以你可以用 ssr: false 
    // 来配置插件只从客户端还是服务端运行
  ]
}

使用Vuex

Nuxt已内置了Vuex,所以不需额外安装和use了。

模块方式

状态树还可以拆分成为模块,store 目录下的每个 .js 文件会被转换成为状态树指定命名的子模块

使用状态树模块化的方式,store/index.js 不需要返回 Vuex.Store 实例,而应该直接将 state、mutations 和 actions 暴露出来:

fetch方法

fetch 方法会在渲染页面前被调用,作用是填充状态树 (store) 数据,与 asyncData 方法类似,不同的是它不会设置组件的数据。

nuxtServerInit方法

如果在状态树中指定了nuxtServerInit方法,Nuxt调用它时会将页面的上下文对象作为第2个参数传给它(仅在服务端调用时)。当我们想将服务端数据传到客户端时,就可用此方法。

如,服务端会话状态树可以通过 req.session.user 来访问当前登录用户。将该登录用户信息传给客户端的状态树,只需要更新 store/index.js,如下:

js
actions: {
  nuxtServerInit({commit}, {req}) {
    if (req.session.user) {
      commit('user', req.session.user)
    }
  }
}

如果你使用状态树模块化的模式,只有主模块(即 store/index.js)适用设置该方法(其他模块设置了也不会被调用)。nuxtServerInit 方法接收的上下文对象和 fetch 的一样,但不包括 context.redirect() 和 context.error()。

命令

命令描述
nuxt启动一个热加载的Web服务器(开发模式) localhost:3000
nuxt build利用webpack编译应用,压缩JS和CSS资源(发布用)
nuxt start以生成模式启动一个Web服务器 (nuxt build 会先被执行)
nuxt generate编译应用,并依据路由配置生成对应的HTML文件 (用于静态站点的部署)

大致就这样了,试着自己折腾一下吧。对了,正好可以把个人网站首页用nuxt重构静态发布~~

生命不息,折腾不止!~

共 20 个模块,1301 篇 Markdown 文档。