前言
Nuxt.js 是一个基于 vue.js 的通用应用框架
主要是用来进行 UI 渲染,服务端渲染(SSR)
Nuxt.js 集成了以下组件/框架,用于开发完整而强大的 Web 应用:
Vue2、Vue-Router、Vuex、Vue服务端渲染(排除使用 mode: ‘spa’)、Vue-Meta
特性
- 基于 Vue.js
- 自动代码分层
- 服务端渲染
- 强大的路由功能、支持异步数据
- 静态文件服务
- ES2015+ 语法支持
- 打包和压缩 JS 和 CSS
- HTML 头部标签管理
- 本地开发支持热加载
- 集成 ESLint 格式规范
- 支持各种样式预处理器:sass、less、stylus 等
- 支持 HTTP/2 推送
流程图
安装
- 初始化并创建一个 Nuxt.js 项目 ```vue 首先执行: vue init nuxt/starter
Generate project in current directory? [yes]
Project name [项目名]
Project description 回车
Author [作者名称]
```javascript
npx create-nuxt-app <项目名>
服务端渲染的好处
- 更好的 SEO,由于所搜引擎爬虫抓取工具可以直接查看完全渲染的页面。
- 对于缓慢的网络或者运行缓慢的设备,提供获取网页速度,有良好的用户体验
- SSR 会减少对服务器的请求。
- 普通页面,会先获取文件,在读取内容,读取到 ajax 的 js 时,在向服务器发送请求,获取内容,这就是至少二次对服务器的请求了
- SSR 直接在服务端渲染为完整的页面,发送到浏览器
Nuxt使用组件
在
nuxt.config.js
中写入以下代码export default { components: true, }
在
pages
目录下的组件中使用即可,无需引入 ```vue // 方法1:当组件在components根目录下时的引入方法// 组件名称
// 方法2:当组件在components/user目录下时的引入方法
> NuxtJS中使用组件需要注意组件的目录等级
<br />
<a name="hpcXq"></a>
# 路由跳转
<a name="nVPZu"></a>
## 基础路由
1. 在NuxtJS中,只需在 `pages`目录下创建组件以及目录即可,无需自己手写路由
1. NuxtJS会自动解析 `pages`目录下的文件路径,随即生成对应的路由
1. NuxtJS中使用路由跳转的方法如下所示:
vue
// 跳转至 user/index.vue 目录下
> 在一个 `pages`目录下或任意子目录下创建 `index.vue` 文件,访问该目录路径,相当于直接访问了该目录下的 `index.vue` 文件
<a name="aJUHU"></a>
## 动态路由
1. 以下划线`_`为前缀的 Vue 文件或目录,都是带有参数的动态路由
matlab
pages/
—| slug/
——-| comments.vue
——-| index.vue
—| users/
——-| _id.vue
—| index.vue
```javascript
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'
}
]
}
## 处理404页面
Nuxt提供了一个专门捕捉 404 的情况,以助于我们更好的实现 404 之后的操作
> 在 pages
目录下创建一个名为 `.vue的vue文件,这个文件是专门用于捕捉 404 页面的,在此文件中可以更好的帮助我们捕捉 404 错误之后的操作
可以在此文件中添加 404 错误之后所需要执行的代码或者页面等
<a name="LlxpG"></a>
# 中间件
<a name="XP6gv"></a>
## 创建
在项目根目录下,与
pages目录同级,创建一个名为
middleware的目录,此目录下的文件就是中间件
<a name="p346I"></a>
## 使用
<a name="FglJK"></a>
### 方法1
在
nuxt.config.js` 文件中直接使用:
javascript
module.export = {
router: {
middleware: 'auto' // auto为中间件名称
}
}
### 方法2
在组件中使用:
```vue
Secret page
``` ## 执行顺序 1. 执行 `nuxt.config.js` 1. 匹配布局 1. 匹配页面 > 中间件可以异步执行,只需要返回一个 `Promise`或使用第 2 个 `callback` 作为第一个参数: ```javascript import axios from 'axios' export default function ({ route }) { return axios.post('http://my-stats-api.com', { url: route.fullPath }) } ``` # Loading 加载 **该属性用于页面跳转和加载页面时使用** ## 使用方法 ```javascript // 在 nuxt.config.js 文件中输入以下代码 module.exports = { loading: true } ``` > 将 true 改为 false,表示禁用加载进度条 ```javascript // 在所需要注册的组件内部输入以下代码 export default { mounted() { this.$nextTick(() => { this.$nuxt.$loading.start() setTimeout(() => this.$nuxt.$loading.finish(), 500) }) } } ``` > 若在 mounted 方法中调用,需使用 this.$nextTick 来调用,Loading 无法立即使用 ## 个性化加载进度条 | **键** | **类型** | **默认值** | **描述** | | --- | --- | --- | --- | | `color` | **String** | `'black'` | 进度条颜色 | | `failedColor` | **String** | `'red'` | 页面加载失败时的颜色(当`data`或`fetch`方法返回错误时) | | `height` | **String** | `'2px'` | 进度条的高度(在进度条元素的`style`属性上体现) | | `throttle` | **Number** | `200` | 在** ms **中,在显示进度条之前等待的时间,用于防止条形闪烁 | | `duration` | **Number** | `5000` | 进度条的最大显示时长,单位** ms****Nuxt.js **假设页面在该时长内加载完毕 | | `continuous` | **Boolean** | `false` | 当加载时间超过`duration`时,保持动画进度条 | | `css` | **Boolean** | `true` | 设置为** false **以删除默认进度条样式(并添加自己的样式) | | `rtl` | **Boolean** | `false` | 从右到左设置进度条的方向 | ## 自定义加载组件 > 新建一个加载组件代替 **Nuxt.js** 默认的,在 `loading` 配置项里指定组件的路径,**Nuxt.js** 会自动调用该组件 自定义组件需要实现以下接口方法: | **方法** | **是否必须** | **描述** | | --- | --- | --- | | `start()` | 是 | 路由更新(即浏览器地址变化)时调用,请在该方法内显示组件 | | `finish()` | 是 | 路由更新完毕(即`asyncData`方法调用完成且页面加载完)时调用,请在该方法内隐藏组件 | | `fail(error)` | 否 | 路由更新失败时调用(如`asyncData`方法返回异常) | | `increase(num)` | 否 | 页面加载过程中调用,`num`时小于 **100** 的整数 | 可以在`components`目录下创建自定义的加载组件,目录为 `components/loading.vue`: ```vue
Loading...
然后更新`nuxt.config.js`,告诉 **Nuxt.js** 使用自定义加载组件:
```javascript
module.exports = {
loading: '~/components/loading.vue'
}
Transition 过渡
使用方法
export default {
// 字符类型
transition: '',
// 对象类型
transition: {},
// 函数类型
transition (to, from) {}
}
只需在某个需要自定义过渡特效的组件中使用即可
<template>
<transition name="test"></transition>
</template>
<script>
export default {
transition: 'test'
}
</script>
// transition 值类型是字符类型,相当于设置了 transition.name 属性
<template>
<transition name="test" mode="out-in"></transition>
</template>
<script>
export default {
transition: {
name: 'test',
mode: 'out-in'
}
}
</script>
更多方法见官网:transition
export default {
transition(to, from) {
if (!from) {
return 'slide-left'
}
return +to.query.page < +from.query.page ? 'slide-right' : 'slide-left'
}
}
/
to/posts
=>slide-left
/posts
to/posts?page=3
=>slide-left
/posts?page=3
to/posts?page=2
=>slide-right
asyncData 异步数据
asyncData
方法会在组件(限于页面组件)每次加载之前被调用,在服务端或路由更新之前被调用
此方法被调用的时候,第一个参数被设定为当前页面的上下文对象,Nuxt会将 asyncData
返回的数据融合组件data
方法返回的数据一并返回给当前的组件
由于
asyncData
方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过this
来引用组件的实例对象
Layouts 布局
nuxt
<template>
<div>
<h1>Welcome</h1>
<NuxtLink to="/about">
About page
</NuxtLink>
</div>
</template>
<script>
export default {
layout: 'dark' // 将 dark.vue 布局组件应用在 index.vue 中
}
</script>
// dark.vue 为布局组件,名字可随意取,默认为 default.vue
<template>
<div>
<Nuxt /> // 此为 pages/index.vue 的容器
</div>
</template>
nuxt-child
<template>
<div>
<h1>我是父级页面</h1>
<nuxt-child :foobar="123" />
</div>
</template>
<template>
<div>
<h1>{{ foobar }}</h1>
</div>
</template>
<script>
export default {
props: ['foobar']
}
</script>
child.vue
若不用props
接收,则nuxt-child
中的属性将渲染为自定义 css 属性
nuxt-link
<template>
<div>
<h1>Home page</h1>
<nuxt-link to="/about">关于</nuxt-link>
</div>
</template>
别名:
<n-link>
、<NuxtLink>
、<NLink>
Configuration 配置
css
// 安装 sass 所需的 npm 包
npm install --save-dev node-sass sass-loader
// nuxt.config.js 配置 css 所需资源
module.exports = {
css: [
// 直接加载一个 Node.js 模块。(在这里它是一个 Sass 文件)
'bulma',
// 项目里要用的 CSS 文件
'@/assets/css/main.css',
// 项目里要使用的 SCSS 文件
'@/assets/css/main.scss'
]
}
component
// nuxt.config.js
export default {
components: true,
}
开启后直接在 pages 目录下的页面组件中使用即可(例:
components/Foo.vue
==<Foo/>
)
router
// nuxt.config.js
module.exports = {
router: {
base: '/app/' // 此时应用的根 url 为 http://localhost:3000/app/
}
}
routeNameSplitter
// nuxt.config.js
export default {
router: {
routeNameSplitter: '/'
}
}
// pages/posts/_id.vue ==> posts-id 修改前
// pages/posts/_id.vue ==> posts/id 修改后
extendRoutes
// nuxt.config.js
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
name: 'custom',
path: '*',
component: resolve(__dirname, 'pages/404.vue')
})
}
}
}
server
// nuxt.config.js
export default {
server: {
port: 8000, // default: 3000
host: '0.0.0.0' // default: localhost,
}
}
// nuxt.config.js
import path from 'path'
import fs from 'fs'
export default {
server: {
https: {
key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
}
}
}
// nuxt.config.js
export default {
server: {
socket: '/tmp/nuxt.socket'
}
}
Programmatically 编程方式
Usage
const { Nuxt } = require('nuxt')
const options = {}
const nuxt = new Nuxt(options)
nuxt.build().then(() => {
// 这里可以用 nuxt.render(req, res) 或者 nuxt.renderRoute(route, context)
})
render
const { Nuxt, Builder } = require('nuxt')
const app = require('express')()
const isProd = process.env.NODE_ENV === 'production'
const port = process.env.PORT || 3000
// 用指定的配置对象实例化 Nuxt.js
const config = require('./nuxt.config.js')
config.dev = !isProd
const nuxt = new Nuxt(config)
// 用 Nuxt.js 渲染每个路由
app.use(nuxt.render)
// 在开发模式下启用编译构建和热加载
if (config.dev) {
new Builder(nuxt).build().then(listen)
} else {
listen()
}
function listen() {
// 服务端监听
app.listen(port, '0.0.0.0')
console.log('Server listening on `localhost:' + port + '`.')
}
Internals 内部构件
Hooks
nuxt.hook('ready', async nuxt => {
// 自定义代码
})
Plugin | Arguments | When |
---|---|---|
ready | (nuxt) | Nuxt 实例初始化 (ModuleContainer 和 Renderer 已经准备好). |
error | (error) | 调用 hooks 时出现未处理的错误。 |
close | (nuxt) | Nuxt 实例优雅地关闭。 |
listen | (server, {host, port}) | Nuxt内部服务器开始监听。 (使用 nuxt start 或 nuxt dev). |