Nuxt 2 项目开发总结

Nuxt 2 项目开发总结

2020年11月13日 阅读:12 字数:969 阅读时长:2 分钟

最近使用Nuxt.js写完了一个项目,做下总结,主要包括插件、中间件、数据请求、部署等问题

最近使用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、常见问题

  1. 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

推荐阅读

恰饭区

评论区 0

0/500

还没有评论,快来抢第一吧