nuxt.js个人使用笔记

Nuxt.js 简介

  • 随着工程量的不断增加,业务处理复杂度提高,传统架构的项目整体加载速度可能会越来越慢;与此同时,SPA 在内的组件化开发对 SEO 也非常不友好。
  • 现在很多应用就开始使用 SSR 来解决这两个问题,但采用 SSR 在另一方面也给服务器增加了压力。
  • Nuxt.js 便是一个支持 SSR 的前端框架,基于 Vue.js,通过对客户端 / 服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染。

官网:https://www.nuxtjs.cn/guide

创建 Nuxt 项目

安装

Nuxt.js 团队创建了脚手架工具 create-nuxt-app,这里直接使用 npx 安装。
期间会提示项目名称、UI 框架、Web 框架、SSR 模式还是单页面模式等的选择,根据自己的需要进行选择。

1
npx create-nuxt-app 项目名

加载

等项目 build 完成,进入项目根目录下启动项目。

1
npm run dev

查看

启动默认端口为3000,在启动完成会给出主页的url,在浏览器输入:

1
http://localhost:3000

目录结构

1
2
3
4
5
6
7
8
9
10
.nuxt       打包的项目
assets 存放资源文件 (图片, 默认 CSS 代码等)
components 组件文件
layouts 布局目录
middleware 中间件
pages 默认路由对应的页面
plugins 插件配置文件
static 静态文件 (也可以存放图片等资源)
store Vuex 文件
nuxt.config.js 配置文件 (vue.config.js 相似)

Nuxt.js 使用

CSS 相关

全局引入

  1. 在 assets 目录下新建 css/global.css 文件,写入如下内容:
    1
    2
    3
    body {
    background-color: red;
    }
  2. 然后在 nuxt.config.js 的 css 下修改为下面配置:
    1
    2
    3
    css: [
    '@/assets/css/global.css'
    ],

注意:Nuxt 团队给出了 nuxt.config.js 中 css 项的加载顺序,是按照 css 的扩展文件名来排序的,而不是单纯的只看前后顺序。
3. 运行项目,可以看到所有项目背景都为红色了。

路由过渡动画

Nuxt.js 使用 Vue.js 的组件来实现路由切换时的过渡动效。
修改上面建的 assets/css/global.css 文件,添加下面样式:

1
2
3
4
5
6
.page-enter-active, .page-leave-active {
transition: opacity .5s;
}
.page-enter, .page-leave-active {
opacity: 0;
}

再次点击跳转,便有了动画效果。

路由

Nuxt 默认会监听 pages 目录下的文件变化,新建 .vue 文件时会自动添加到路由中,路由模式便是文件的位置信息,可在 .nuxt/routes.json 中查看。

基础路由

pages的目录结构:

1
2
3
4
5
pages/
--| user/
-----| index.vue
--| index.vue
--| test.vue

routes.json自动生成的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'test',
path: '/test',
component: 'pages/test.vue'
},
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
}
]

路由跳转

1
2
3
<template>
<nuxt-link to="/">首页</nuxt-link>
</template>

动态路由

需要创建对应的以下划线作为前缀的 Vue 文件或目录:

1
2
3
4
pages/
--| users/
-----| _id.vue
--| index.vue

routes.json 自动生成的配置:

1
2
3
4
5
6
7
8
9
10
11
12
[
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
}
]

users-id 的路由路径带有 :id? 参数,表示该路由是可选的,可在跳转时传递参数。

1
2
3
<template>
<nuxt-link to="/users/123">首页</nuxt-link>
</template>

users/_id.vue 页面中获取参数:

1
let param = this.$route.params.id;

嵌套路由

嵌套路由,可在页面中嵌套子页面,可用于 table 切换之类的场景。

1
2
3
4
5
pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue

routes.json 自动生成的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[
{
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-child 显示子页面,默认显示 users/index.vue,切换子页面同样使用:nuxt-link 。

1
<nuxt-child keep-alive :foobar="123"></nuxt-child>

中间件

中间件允许您定义一个自定义函数运行在一个页面或一组页面渲染之前,每一个中间件应放置在 middleware 目录下。

比如我可以利用中间件,来进行路由跳转时的验证:

  1. 新建middleware/auth.js文件,写入如下内容:
1
2
3
4
export default function (context) {
console.log("start");
context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent;
}
  1. nuxt.config.js文件中添加:
1
2
3
router: {
middleware: 'auth'
}
  1. 再次运行,便可看到每次打开页面都会打印日志。

布局

默认布局

可通过添加 layouts/default.vue 文件来扩展应用的默认布局。
但一定要添加显示页面的主体内容。

1
2
3
4
5
6
<template>
<div>
<div>标题</div>
<nuxt />
</div>
</template>

错误页面

新建layouts/error.vue文件,添加如下内容,样式可自己修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div class="container">
<h1>404</h1>
<h1 v-if="error.statusCode === 404">页面不存在</h1>
<h1 v-else>应用发生错误异常</h1>
<nuxt-link to="/">首 页</nuxt-link>
</div>
</template>

<script>
export default {
props: ['error'],
layout: 'blog' // 你可以为错误页面指定自定义的布局
}
</script>
<style>
.container {
width: 20%;
margin: 50px auto;
}
</style>

异步数据

asyncData

asyncData 方法会在组件 (限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。

在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData 方法来获取数据,Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
import axiox from 'axios';
export default {
async asyncData({params}) {
return axiox.get("http://localhost/GetData/" + params.id)
.then(res => {
console.log(res.data.title)
return {title: res.data.title}
});
},
data() {
return {
title: 'NG'
}
}
}
</script>

async / await

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
import axiox from 'axios';
export default {
async asyncData({params}) {
const { data } = await axiox.get("http://localhost/GetData/" + params.id);
console.log(data);
return {title: data.title}
},
data() {
return {
title: 'NG'
}
}
}
</script>

回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
import axiox from 'axios';
export default {
asyncData({params},callback) {
axiox.get("http://localhost/GetData/" + params.id)
.then(res => {
console.log(res.data.title)
callback(null, { title: res.data.title })
});
},
data() {
return {
title: 'NG'
}
}
}
</script>