最近在做一些网站首页的需求,需要支持seo,然后就是使用了nuxt来做服务端渲染
一. 初步入门
先看官方文档了解其基本特性nuxt.cn,大致使用和vue差别不大,有以下几点不一样
1.nuxt 路由跟page文件夹下文件的命名有很大关系,并不需要额外进行路由文件的配置。
2.服务端渲染涉及到了动态数据请求的问题,在需要服务端渲染的页面若需要调用接口可使用asyncData完成,但是asyncData函数拿不到当前实例this,但是能拿到上下文对下context这个很有作用
3.nuxt的插件系统在整个使用nuxt的过程中使用的很频繁,基本上每引用一个第三方插件都需要在plugin下加一个js,在plugin里可以拿到上下文对象,一般用的比较多的就是$axios, redirect, store, app
二.项目中用到的模块
1.@nuxtjs/axios,
之前在axios和@nuxtjs/axios之间纠结,最终还是选用了@nuxtjs/axios,它的使用方法也比较简单@nuxtjs/axios,在这次的项目中写了一个api文件传入$axios,然后使用plugin的inject方法在this和app下都注入了api方便后续接口调用
api/api.js
export default ($axios) => ({
getList(params, config) {
return $axios.$get('/api/list')
}
plugin/axios-api.js
import api from '~/api/api.js'
export default ({ $axios }, inject) => {
const axiosApi = api($axios)
for (const [key, value] of Object.entries(axiosApi)) {
inject(key, value)
}
}
nuxt-config.js中要引入这个js
// 在asyncData中使用
async asyncData({ app }) {
let result = await app.$getList()
}
// 在普通函数中使用
async getLists() {
let res = await this.$getList()
}
全局拦截 plugin/axios.js
import { Message } from 'element-ui'
export default function ({ $axios, redirect, store, app }) {
$axios.onRequest((config) => {
})
$axios.onResponse((res) => {
})
$axios.onError((error) => {
if (response && response.status !== 200) {
if (response.status === 401) {
redirect(跳转链接)
}
if (response && response.config.server) {
store.commit(
'setError',
(error && error.message) || '网络错误,请稍后重试'
)
} else {
Message.error(
app.i18n.t((error && error.message) || '网络错误,请稍后重试')
)
}
}
})
}
由于在asyncData中接口出错无法弹窗提示,于是我在axios拦截函数中把错误信息存在vuex里,等页面渲染时再查看vuex中是否有错误信息要弹出,为了及时清除掉错误信息,在element的message组件关闭的回调函数中清除vuex中的错误信息
openServerError() {
const { error } = this.$store.state
if (error) {
const that = this
this.$notify({
type: 'error',
message: error,
onClose() {
that.notifyClose()
},
})
}
},
notifyClose() {
this.$store.commit('deleteError')
},
2.nuxt-i18n
项目的国际化使用了nuxt-i18n,官方文档nuxt-i18n 配置很简单按照文档上的来就行。 由于nuxt国际化默认后面是带上语言参数的,有个需求是希望改变cookie刷新页面,网页自动定位到相应语言的页面。之前的思路是在middleware中加个判断要是英文的路径中没有en统一加个en,中文的有en就给去掉,最后试下来middleware中使用redirect时常使网页重定向次数过多从而崩溃,后来仔细研究官方文档,发现几个属性配合起来使用就能达到我的目的了
i18n: {
locales: [
{
code: 'zh',
iso: 'zh',
file: 'cn.js'
},
{
code: 'en',
iso: 'en',
file: 'en.js',
},
],
defaultLocale: 'zh',
vueI18n: {
fallbackLocale: 'zh',
silentTranslationWarn: true, //使浏览器不提示vue i18n的warning
},
seo: true,
lazy: true,
langDir: 'i18n/',
//主要是这几个参数
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'cookieName',
alwaysRedirect: true,
cookieDomain: 'your domain',
},
},
国际化的时候还遇到了element按需引入国际化的问题,通过查看element的官方文档找到了解决方法
import ElementLocale from 'element-ui/lib/locale'
ElementLocale.i18n((key, value) => app.i18n.t(key, value))
3.@nuxtjs/device
检测当前使用设备pc端还是移动端,还可以判断是windows还是mac 还是isAndroid或iphone,注意在iphone里instance.$device.isMacOS也是true注意判断的先后顺序
4.dayjs
这是一个轻量级的js时间处理的npm 包,之前本来用的是moment后来组长分析代码性能说是这个包太大了占了整个代码量的25%遂换成了也能满足需求的dayjs使用方法几乎和moment一模一样
5.vue-observe-visibility
检测浏览器的滚动位置,可以等页面滚动到相应位置再调用接口
6.nuxt-helmet
7.nuxt build --analyze
可使用"build:check": "nuxt build --analyze",分析代码
三.遇到的坑
1.nuxt有个static文件夹文档上说放在里面的文件跟路径下可以访问,但是自己在根路径下加了一个文件却始终访问不到,后来才知道在发布的时候得把static文件拷贝出来放在根路径下才行。应为nuxt build的时候没有打包static,build之后就没有static了
2.移动端列表页需要滚动加载,使用了element的InfiniteScroll 无限滚动,这个对样式有要求,而且滚动加载的区域要设置高度,就会导致数据还没加载完可能页面就滑到了底部,样式上会给人造成错觉,目前还没解决
3.nuxt 使用插件的时候将插件命名为xxx.client.js,那么插件只会在里面时才会渲染。当时在项目中有三个地方使用了perfect-scrollbar这个插件,后面两个地方渲染了,第一个地方始终没渲染,后来才知道第二个地方使用了插件才开始渲染。
四.心得
遇到问题一定要好好研究文档,成熟的框架,模块基本上有你想要的东西,不必自造轮子