• Nuxt.js项目实战


    感悟

    经过几个周六周日的尝试,终于解决了服务端渲染中的常见问题,当SEO不在是问题的时候,或许才是我们搞前端的真正的春天,其中也遇到了一些小坑,Nuxt.js官方还是很给力的,提issue后很积极的给予帮助,再次感谢Nuxt.js的开发团队。

    路由鉴权

    第一个拦路虎就是登陆时候的鉴权问题,如何把token保存到本地。官方使用express-session解决这个问题,但是这样做后端也需要使用nodejs,而我们公司使用的PHP。转念一想或许cookie可以一试,于是我是这样做的:

    app.post('/api/login', function (req, res) {
      // 后台验证用户信息,并返回token
      async function login () {
        const { data } = await axiosServer.post('/login', req.body)
        return data
      }
    
      login().then(function (data) {
        // 把token存储到cookie中
        const { token } = data
        if (token) {
          res.cookie('token', token, {
            maxAge: 60000 * 60 * 24
          })
        }
        // 原封不动返回
        return res.json(data)
      })
    })
    

    我把登录请求用nodejs做了一次转发,把用户提交的数据传给后端,后端返回的token设置到cookie里,然后把数据返会给前端,前端再用vuex保存token状态,这样token同时存在于cookie和内存里,刷新页面也是正常的
    前端存储token:

      async nuxtServerInit ({ dispatch, commit }, { req, res }) {
        if (req.cookies && req.cookies.token) {
          // 存储token
          commit('SET_USER', req.cookies.token)
        }
      },
      // SET_USER
      SET_USER (state, token) {
        state.token = token
      },
    

    于是这个问题就这样解决了,所有需要存储到本地的数据都可以这样做来解决

    渲染组件内的数据

    另一个小问题是components里数据如何渲染。在Nuxt.js中只有page里的组件有fetchasyncData方法,所以当我们使用layout布局页面时如果组件需要请求数据,就无法渲染了,解决方法是在nuxtServerInit方法里初始化组件内的数据,如下:

      async nuxtServerInit ({ dispatch, commit }, { req, res }) {
        // 初始化组件内的数据
        await dispatch('ADMIN_INFO')
        await dispatch('TAGS')
        await dispatch('ARCHIVES')
      }
    

    这样组件内的数据也可渲染成功了

    过滤器的使用

    Nuxt.js的plugins设计的个人感觉还是很人性化的,用起来简直是不能再简单。在plugins新建一个filters.js,过滤器可以这样玩:

    import Vue from 'vue'
    // 时间格式化
    export function formatDate (date, fmt) {
      let newDate = new Date(date)
      if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (newDate.getFullYear() + '').substr(4 - RegExp.$1.length))
      }
      let o = {
        'M+': newDate.getMonth() + 1,
        'd+': newDate.getDate(),
        'h+': newDate.getHours(),
        'm+': newDate.getMinutes(),
        's+': newDate.getSeconds()
      }
      for (let k in o) {
        if (new RegExp(`(${k})`).test(fmt)) {
          let str = o[k] + ''
          fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
        }
      }
      return fmt
    }
    let filters = {
      formatDate
    }
    
    Object.keys(filters).forEach(key => {
      Vue.filter(key, filters[key])
    })
    export default filters
    

    然后在nuxt.config.js中注册一下:

      plugins: [
        '~plugins/filters.js'
      ]
    

    在组件中就可以这样happy的用起来了:

    <!-- 时间格式化 -->
    <div>
     <span>{{date | formatDate('yyyy-MM-dd')}}</span>
    </div>
    

    中间件

    比如说用户未登录状态下,通过路由闯入了需要鉴权的页面,我们可以自定义一些错误:

    // auth.js
    export default function ({ store, error }) {
    // 可通过组件的props接收error信息
      if (!store.state.token) {
        error({
          message: 'cookie失效或未登录,请登录后操作',
          statusCode: 403
        })
      }
    }
    
    

    在组件中使用该中间件:

    export default {
      middleware: 'auth',
      // 还可以把用户重定位到登录页
      fetch ({redirect, store}) {
        if (!store.state.token) {
          redirect('/login')
        }
      },
    }
    

    多级路由嵌套

    官方说这种情况用的较少,但是我发现用的挺多的,比如说不同分类又有不同分页,这样分类和分页都要是动态路由,如图所示:


    编译后的结果:

    项目部署

    大概在8月份时候,写了几篇关于如何部署nodejs项目的文章,回头看写的果然比较菜,随着时间推移,修复了一些错误,发现了一些错误,整体写的太乱。于是抽了一天时间,在新的服务器上一边实践一边记录,把上面几篇文章用gitbook汇总了一下,不在这里展开了,太长了,增加了自动部署的相关内容

    项目实践

    这个小项目是我在几月前写的,最近一月用Nuxt.js进行了重构,前端使用了Nuxt.js + vuex,后端使用了Nodejs + MongoDB, 用vue写了一个markdown编辑器,支持图片上传和服务端渲染,效果图:

    首页

    编辑器


    GitHub
    gitbook

  • 相关阅读:
    Educational Codeforces Round 83 --- F. AND Segments
    Educational Codeforces Round 83 --- G. Autocompletion
    SEERC 2019 A.Max or Min
    2019-2020 ICPC Southwestern European Regional Programming Contest(Gym 102501)
    Educational Codeforces Round 78 --- F. Cards
    今天我学习了一门全新的语言
    codeforces 1323D 题解(数学)
    Educational Codeforces Round 80 (Div. 2) 题解 1288A 1288B 1288C 1288D 1288E
    Educational Codeforces Round 81 (Div. 2) 题解 1295A 1295B 1295C 1295D 1295E 1295F
    Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F
  • 原文地址:https://www.cnblogs.com/yesyes/p/7977161.html
Copyright © 2020-2023  润新知