记录一下初学nuxt.js的知识点📕

介绍

官网:https://zh.nuxtjs.org/guide

特性:

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

安装

1
vue init nuxt-community/starter-template <project-name>

ps: 如果没有安装 vue-cli ,需先通过 npm i -g vue-cli 来安装

安装依赖包

1
2
cd <project-name>
npm install

启动项目

1
npm run dev

应用运行在:http://localhost:3000 ,后面讲如何修改默认端口。

目录结构说明

1
2
3
4
5
6
7
8
9
10
├── assets //用于组织未编译的静态资源如 LESS、SASS 或 JavaScript。
├── components //用于组织应用的 Vue.js 组件。
├── layputs //用于组织应用的布局组件。
├── middleware //用于存放应用的中间件。
├── pages //用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。
├── plugins //用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。
├── static //用于存放应用的静态文件。
├── store //用于组织应用的 Vuex 状态树 文件。
├── nuxt.config.js //用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。
└── package.json //用于描述应用的依赖关系和对外暴露的脚本接口。

路由

Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。

假设 pages 的目录结构如下:

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

那么,Nuxt.js 自动生成的路由配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.js 默认的应用模板。

定制化默认的 html 模板,只需要在应用根目录下创建一个 app.html 的文件。

默认模板为:

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>

布局

  • 默认布局
1
2
3
<template>
<nuxt/>
</template>
  • 个性化布局

layouts 根目录下的所有文件都属于个性化布局文件,可以在页面组件中利用 layout 属性来引用。

请确保在布局文件里面增加 <nuxt/> 组件用于显示页面非布局内容。

for example: layouts/default.vue

1
2
3
4
5
6
<template>
<div>
<div>这里是导航内容</div>
<nuxt/>
</div>
</template>

在 pages/index.vue 里,可以指定页面组件使用该布局

1
2
3
4
5
<script>
export default {
layout: 'blog'
}
</script>

页面

页面组件实际上是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项(对应 Nuxt.js 提供的功能特性)以便你能快速开发通用应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<h1 class="red">Hello {{ name }}!</h1>
</template>

<script>
export default {
asyncData (context) {
// called every time before loading the component
return { name: 'World' }
},
fetch () {
// The fetch method is used to fill the store before rendering the page
},
head () {
// Set Meta Tags for this Page
},
// and more functionality to discover
...
}
</script>

<style>
.red {
color: red;
}
</style>

插件

使用 element UI

首先增加文件 plugins/element-ui.js

1
2
3
4
import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(Element, { size: 'small' })

在 nuxt.config.js 中配置

1
2
3
plugins: [
'~plugins/element-ui'
]

只在浏览器里使用的插件

nuxt.config.js

1
2
3
4
5
module.exports = {
plugins: [
{ src: '~plugins/element-ui', ssr: false }
]
}

异步数据

asyncData

在渲染组件之前异步获取数据。

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

1
2
3
4
5
6
7
8
export default {
async asyncData (context) {
let data = await axios.get('http://www.xxx);
return {
title: data.title
}
}
}

fetch

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

如果页面组件设置了 fetch 方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前)。

fetch 方法的第一个参数是页面组件的上下文对象 context,我们可以用 fetch 方法来获取数据填充应用的状态树。为了让获取过程可以异步,你需要返回一个 Promise,Nuxt.js 会等这个 promise 完成后再渲染组件。

1
2
3
4
5
6
export default {
async fetch({store, params}) {
let data = await axios.get('http://www.xxx')
store.commit('setValues', data);
}
}

配置项

nuxt.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
module.exports = {
head: {
title: 'douban',
meta: [
{
charset: 'utf-8'
},{
name: 'viewport',
content: 'width=device-width,initial-scale=1'
},{
hid: 'description',
name: 'description',
content: 'Meta description'
}
],
//ali iconfont
link: [
{
'rel': 'stylesheet',
'href': '//at.alicdn.com/t/font_562725_orktergz2etawcdi.css'
}
]
},
css: [
{
src: '~assets/css/reset.scss',
lang: 'scss'
},{
src: '~assets/css/style.scss',
lang: 'scss'
}
],
loading: {
color: '#00b600',
height: '2px',
failedColor: 'red'
},
plugins: [
'~plugins/filters',
'~plugins/element-ui'
],
build: {
vendor: ['axios']
},
router: {
linkActiveClass: 'active-link',
}
}

常见问题

修改端口号

package.json

1
2
3
4
5
6
7
8
9
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "4000"
}
},
"scripts": {
"dev": "nuxt"
}

使用外部资源

在 nuxt.config.js 中配置你想引用的资源文件:

1
2
3
4
5
6
7
8
9
10
module.exports = {
head: {
link: [
{
'rel': 'stylesheet',
'href': '//at.alicdn.com/t/font_562725_orktergz2etawcdi.css'
}
]
}
}

局部配置
可在 pages 目录内的 .vue 文件中引用外部资源,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<h1>使用 jQuery 和 Roboto 字体的关于页</h1>
</template>

<script>
export default {
head: {
script: [
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js' }
]
}
}
</script>

meta 标签重复

为了避免子组件中的meta标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为meta标签配一个唯一的标识编号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
head: {
title: 'starter',
meta: [
{
charset: 'utf-8'
},
{
name: 'viewport',
content: 'width=device-width,
initial-scale=1'
},
{
hid: 'description',
name: 'description',
content: 'This is the generic description.'
}
],
}