最近使用Nuxt.js写完了一个项目,做下总结,主要包括插件、中间件、数据请求、部署等问题
1、插件
nuxt.config.js
module.exports = {
plugins: [
'@/plugins/element-ui',
'@/plugins/axios'
]
}
1.1、Axios
设置axios服务地址,请求与响应拦截器
plugins/axios.js
export default function ({ $axios, error }) {
// url = base url + request url
$axios.defaults.baseURL = 'http://127.0.0.1:8360/front'
// request timeout
$axios.defaults.timeout = 15000
$axios.onResponse((response) => {
const { errno } = response.data
if (errno !== 0) {
error({ statusCode: 404, message: '哎呀,假装页面未找到' })
}
return response.data
},
(err) => {
error({ statusCode: 500, message: '哎呀,服务器发生错误' })
)
}
1.2、Element-ui
按需引入,全局配置element-ui组件尺寸、层级
plugins/element-ui.js
import Vue from 'vue'
// @see https://element.eleme.cn/#/zh-CN/component/quickstart
import 'element-ui/lib/theme-chalk/index.css'
import {
Pagination,
Menu,
Submenu,
MenuItem
} from 'element-ui'
Vue.use(Pagination)
Vue.use(Menu)
Vue.use(Submenu)
Vue.use(MenuItem)
Vue.prototype.$ELEMENT = {
size: 'small',
zIndex: 2000
}
2、中间件
客户端未登录拦截。服务端获取cookie可以使用cookie-universal-nuxt
import Cookies from 'js-cookie'
const whiteList = ['/login'] // no redirect whitelist
export default async function ({ redirect, store, route }) {
const { path } = route
// determine whether the user has logged in
const hasToken = Cookies.get('token')
if (hasToken) {
if (path === '/login') {
// if is logged in, redirect to the home page
redirect({ path: '/' })
} else {
const hasGetUserInfo = store.getters.userinfo.
if (!hasGetUserInfo) {
try {
// get user info
await store.dispatch('user/getInfo')
} catch (error) {
console.error(error)
redirect(`/login?redirect=${path}`)
}
}
}
} else if (!whiteList.includes(path)) {
/* has no token */
// other pages that do not have permission to access are redirected to the login page.
redirect(`/login?redirect=${path}`)
}
}
3、数据请求
3.1、nuxtServerInit
仅在服务器端调用以预填充 Vuex 存储操作。适用于获取菜单、系统配置等只需要在页面初始化,在客户端切换路由不需要重新获取的数据。
store/index.js
const actions = {
async nuxtServerInit ({ commit }, { req, $axios }) {
// 获取菜单以及系统配置
const { categories, configs } = await $axios.$get('/general')
}
}
3.2、fetch
fetch发生在created之后,页面渲染之前,此时页面已经打开了,如果发生了错误,那么$fetchData.error为true,页面还是可以打开的。
fetch在页面和组件都可以执行,不能传参数,需要通过this.$nuxt.context获取context。
可以操作页面上data中的对象,可以通过$fetchState获取fetch的状态。
<template>
<div>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt Mountains</h1>
<ul>
<li v-for="mountain of mountains">{{ mountain.title }}</li>
</ul>
<button @click="$fetch">Refresh</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>
3.3、asyncData
asyncData发生在路由阶段,beforeCreate之前,如果请求发生错误会进入错误页面;如果请求成功返回的结果将和页面上data进行合并,再渲染页面。
asyncData只是在页面可以使用,无法访问组件实例 ( this
),但是可以接收context
参数。
可以搭配@nuxtjs/axios
、@nuxt/http
等模块使用。
export default {
async asyncData({ params, $axios }) {
const post = await $axios.$get(`http://xxx/posts/${params.id}`)
return { post }
}
}
3.4、watchQuery
watchQuery 属性观察查询字符串并在更改时执行组件方法(asyncData、fetch、validate、layout...)
export default {
watchQuery: ['page']
}
http://127.0.0.1:8360/posts?page=1
当page查询参数改变时,会执行组件asyncData、fetch等方法,可以重新请求数据
4、部署
4.1、SPA单页应用
生成静态 Web 应用程序,客户端渲染
nuxt.config.js
module.exports = {
buildDir: 'www/nuxt-admin',
generate: {
dir: 'www/nuxt-admin',
fallback: 'index.html'
},
ssr: false, // Disable Server Side rendering
target: 'static'
}
4.2、Node.js中间件
将Nuxt作为Node服务的中间件
server.js
const { Nuxt, Builder } = require('nuxt')
const app = require('express')()
const port = 8360
// We instantiate Nuxt with the options
const config = require('./nuxt.config.js')
const nuxt = new Nuxt(config)
app.use(nuxt.render)
// Build only in dev mode
if (config.dev) {
new Builder(nuxt).build()
}
// Listen the server
app.listen(port, '0.0.0.0').then(() => {
console.log(`Server is listening on port: ${port}`)
})
package.json
{
"scripts": {
"dev": "node server.js",
"build": "nuxt build",
"start": "NODE_ENV=production node server.js"
}
}
5、常见问题
- window or document undefined
由于这是服务器端渲染。如果需要指定仅在客户端导入资源,则需要使用该process.client
变量
if (process.client) {
require('external_library')
}
如果仅在客户端运行或依赖Dom元素渲染完成,需要在mounted
生命周期或this.$nextTick()
中执行
export default {
mounted () {
document.documentElement.classList.add('silent')
}
}
参考文档:
https://nuxtjs.org/docs/features/rendering-modes
http://www.qiutianaimeili.com/html/page/2021/02/2025fwfhjlivlut.html
还没有评论,快来抢第一吧