基本概念
中间件: 在一个页面渲染前执行
插件: 运行之前执行js脚本, 注入全局工具函数、配置信息等
模块: 扩展与封装Nuxt功能的模块【官方 模块】
context
context 存在于"validate" 、asyncData"、"plugins"、"middlewares"、"modules" 和 "store/nuxtServerInit" 等
context可用属性
app(Vue根实例)
route(Vue路由对象)、params(route.params的别名)、query(route.query的别名)
store(Vuex.store实例)
isServer&isClient(环境判断)【 全局使用process.server 或 process.client 】
req&res(请求头&响应头) 注意判断process.server, 客户端为undefined
redirect(用于路由重定向, 默认返回状态码302)
error(展示错误页面并传递params)
nuxtState(获取nuxt状态, layout、config、routePath、serverRendered等)
beforeNuxtRender(更改nuxt状态) 只能在服务端调用
$config(runtime config配置)
nuxtServerInit
渲染前填充Vuex.state 第一个参数为store、第二个为context
export const actions = {
async nuxtServerInit({ commit }, { $api, $config, req }) {
// console.log(req.headers.cookie) // 获取到cookie
commit('setRuntimeEnv', $config.runtimeEnv)
}
}
plugins 插件
运行之前执行js脚本, 注入全局配置. 使用inject注入后可在context、Vue实例、Vuex实例加$访问
// nuxt.config.js
module.exports = {
plugins: [
'@/plugins/apis.js',
'@/plugins/common.js'
]
}
// /plugins/apis.js api注入
import apiConfig from '~/utils/api-config'
export default function ({ app: { $axios } }, inject) {
let apis = {}
Object.keys(apiConfig).forEach((item) => {
let curItem = apiConfig[item]
apis[item] = function (params = {}) {
if (curItem.method === 'get') params = { params }
return $axios[curItem.method](curItem.url, params, { headers: curItem.headers || { } })
}
})
inject('api', apis)
}
modules 模块
扩展与封装Nuxt功能的模块【官方模块&开发指南】
// nuxt.config.js
module.exports = {
modules: [
'@nuxtjs/axios', // 向context、Vue实例、Vuex实例注入 $axios
]
}
middleWare 路由中间件
在一个页面渲染前执行. global -> layout -> page
// middleware/auth.js
export default function (ctx) {
console.log('auth middleware') // 例如用于校验token是否过期
}
// global 全局中间件,每个路由都会走进来一次
// nuxt.config.js
module.exports = {
router: {
middleware: ['auth']
}
}
// layout/default.vue 布局中间件
export default {
name: 'Default',
middleware: ['auth']
}
// page/index.vue 页面中间件
export default {
name: 'Index',
middleware: ['auth']
}
serverMiddleware 服务中间件
-
nuxt提供的API,启用后会在其内部创建connect instance.可用于编辑后端逻辑.
-
在vue-server-renderer之前执行且不会通过nuxt服务.
// nuxt.config.js
module.exports = {
serverMiddleware: [
'~/serverMiddleware/test'
]
}
// /serverMiddleware/test.js
export default {
path: '/test',
handler(req, res, next) {
// console.log(require('connect'))
res.end('Everything ok!')
}
}
组件内更新对象
执行顺序: middleware => validate => asyncData => fetch => head
middleware
-
String || Array || Function. 前端路由切换(nuxt-link)时在asyncData前执行
-
使用行为应与asyncData保持一致,即在pages下组件内调用
validate
-
验证动态路由参数是否合法. 必须return true才能正确往下渲染. return false会被重定向到error页
-
在asyncData前执行,使用行为应与asyncData保持一致,即在pages下组件内调用
asyncData
-
返回值为Promise时会等待resolve完成才会继续往下执行, 返回reject时如果没有catch会报错
-
该方法只注册在pages下面的vue组件, 即不支持components与layouts下的组件(写了没反应), 想让该类组件支持服务端渲染只能通过props传递.【注意: 即使是pages下的vue组件, 当成子组件使用时,asyncData也不会触发】
-
只有首屏在服务端渲染,前端路由切换(nuxt-link)时会beforeCreate钩子前调用. Vue的钩子beforeCreate 和 created会在客户端和服务端被调用, 其他生命周期函数仅在客户端被调用
-
无论在server还是在client端, 此钩子中的this为undefined
fetch
-
只有首屏在服务端渲染,前端路由切换(nuxt-link)时会在 beforeMount 钩子后 mounted 钩子前调用. 无论在服务端还是客户端都能获取到context中的store对象(即在客户端页可以更改Vuex的state)
-
使用行为应与asyncData保持一致,即在pages下组件内调用
head
Object || Function. 如果是函数可以使用this获取data数据
key
会应用到router-view的属性中,避免同一路由相同组件服用时导致不能重新渲染的问题
layout
设置布局组件,默认为default。布局组件应添加坑位
控制当前页的滚动行为
transition
当前页面的动画切换控制
watchQuery
-
Boolean || Array. 默认false. 为数组时可指定需要监听的query
-
监听url的query变化,重新执行asyncData, fetch, validate, layout等. 触发后,这些函数一般在客户端执行
Nuxt完整生命周期
Start => Nuxt hooks => serverMiddleware => plugins => nuxtServerInit => Middleware(global->layout->page) => asyncData=> beforeCreate => created => fetch => HTML rendering
常用功能项
全局css配置
loading配置
运行时全局变量注入
serverMiddleware服务端渲染中间件
默认html模板配置
自定义布局layout
坑: 完整匹配layouts目录下组件名称, 大小写敏感.
Nuxt给vue组件注入的方法
页面组件扩展方法一览: asyncData、fetch、validate、head、layout、loading、transition、scrollToTop、middleware
Vuex模块化
静态资源引入处理
全局变量注入
内置组件 [nuxt的key值定义]()、nuxt-child缓存(keep-alive)、nuxt-link预加载(prefetch)
其他
nuxt.config.js
- components: true // 自动注册components下的组件为全局组件
$nuxt
Nuxt.js提供的客户端window/Vue组件对象( 通过window.$nuxt或this.$nuxt访问)
常用构建配置
nuxt.config.js
端口配置
server: {
port: 8000,
host: 'localhost',
disableHostCheck: true
}
禁止数据收集
telemetry: false
全局变量注入
nuxt start会同时注入context、Vue实例、Vuex.store实例的运行时环境变量(服务端&客户端均可读). 通过context.$config.xxx访问
也可配置env使用,但是在docker集群中无效. env配置方法
publicRuntimeConfig: {
runtimeEnv: process.env.CUR_ENV
}
// 服务端访问
asyncData(ctx) {
console.log(ctx.$config.runtimeEnv)
}
// 客户端访问
mounted(ctx) {
console.log(this.$config.runtimeEnv)
}
// Vuex访问
export const actions = {
async nuxtServerInit({ commit }, { $api, $config, req }) {
console.log(this.$config.runtimeEnv)
}
}
代{过}{滤}理配置
modules: [
'@nuxtjs/axios', // 注入 $axios Doc: https://axios.nuxtjs.org/usage
],
axios: {
proxy: true, // 启动代{过}{滤}理转发
proxyHeaders: true // 转发请求头部信息, 默认true
},
proxy: [
["/v1/", {target: 'http://localhost:3000' }]
]
全局头部
head: {
title: '页面标题',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'description' }
],
link: [
// 应用启动后static目录下的文件会映射至应用的根路径 / 下
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'stylesheet', href: '/animate.min.css' }
]
}
顶部loading条
loading: { color: '#E90300' },
<!--可自定义配置组件-->
// loading: '~/components/loadingTab.vue',
全局css & scss变量混入
modules: [
"@nuxtjs/style-resources", // 全局scss注入的插件
],
css: [
'./assets/style/reset.css',
// 巨坑:在styleResources.scss引入global.scss会加入作用域,导致不能全局生效
'./assets/style/scss/global.scss',
],
styleResources: {
scss: [
'./assets/style/scss/variable.scss', // 优先引入scss变量, 下面俩个才能引用
'./assets/style/scss/element-variable.scss',
'./assets/style/scss/mixins.scss',
]
}
vue-router扩展
router: {
middleware: ['auth'],
extendRoutes(routes) {
// params&props解耦操作
const appendPassProps = function(rs) {
for (const route of rs) {
route.props = /:/.test(route.path)
if (route.children) {
appendPassProps(route.children)
}
}
}
appendPassProps(routes)
return routes
},
// 页面跳转滚动条配置
scrollBehavior(to, from, savedPosition) {
// 前进后退保持滚动条位置不变
if (savedPosition) { return savedPosition }
// 路由跳转滚动顶部
return { x: 0, y: 0 }
}
}
build构建配置
build: {
transpile: [/^element-ui/], // node_modules下需要使用babel转译的库
parallel: true, // 多进程打包(提升构建速度)
cache: true, // 构建文件缓存(提升构建速度)
extractCSS: CUR_ENV !== 'local' // 提取内联css到单独文件【与parallel多进程冲突,开发时需关闭】
}