nuxt 使用总结

1,378 阅读4分钟

最近在做一些网站首页的需求,需要支持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这个插件,后面两个地方渲染了,第一个地方始终没渲染,后来才知道第二个地方使用了插件才开始渲染。

四.心得

遇到问题一定要好好研究文档,成熟的框架,模块基本上有你想要的东西,不必自造轮子