要么改变世界,要么适应世界

使用Nuxt改造博客前端

2022-05-07 15:42:34
449
目录

前言

是的,没错,我又来对我的博客系统下手了!回想起2020年,第一次使用hexo搭建的静态博客,那是我对博客系统的初体验,当时搭建完毕后,到处找插件,找主题,心情也很激动,因为这是我的第一个网站,当时熬夜搭建网站的激动现在仍然可以体会得到!

后来慢慢地接触到了动态博客的概念,进一步了解到了typecho,为了搭建它,我自己开始租借服务器,开启了玩转服务器之旅。

使用了typecho大概半年以后,逐渐感受到许多不便,特别是该博客使用的是PHP语言开发的,我没有接触过,也暂时不想接触,想要实现某些自定义功能的时候,无从下手。

于是,出于程序员的理念:

当你觉得某个东西不好用的时候,那你就自己造它。

我决定自己开干!自己编写一个博客系统!

口号喊得虽然很响,但是激情过后就是无尽的迷茫,自己根本无从下手,但是自己立下的誓言含泪也要完成吧!然后自己在在网上找了很多搭建博客的教程,但是要么就是没有文档,要么就是就给了截图,源码都不提供。不过我也能理解,几乎没有人愿意将从零搭建博客的过程全都记录下来吧,那样子太费时间了。

直到后来,在哔哩哔哩上面找到了李仁密老师的小而美的博客教程,上面详细介绍了如何使用SpringBoot搭建个人博客,然后我就跟着作者一行一行地敲代码,不过到后面我逐渐明白了怎么搭建以后,有一些代码就跟作者不一样了,不过90%左右的代码还是和作者一样的。

时间来到了21年年初,我又开始接触到了前后端分离的概念,觉得这玩意挺新奇的,我就萌发了改造博客的想法,不过要改的话,要改的地方有很多,主要是涉及前端页面的都要重新做,但是我的审美一直不在线,最后设计出来的页面差强人意。然后前端使用VueElement-UI,后端之前根据李仁密老师的教程,持久层使用的是Hibernate,然后我这次使用的是Mybatis,其他的思想沿用之前的想法。不过改完以后,有一个致命的弱点,那就是首页访问速度贼慢!而且如果我们尝试在浏览器中查看源码,我们获取到的就是只有一堆js文件,这样子就非常不利于搜索引擎,也就是说如果我不将我的博客链接发出去,那么就几乎不可能有人找得到我的博客。我原本写博客就是为了想分享一下自己的学习心得,或者和其他人一起交流,改造博客以后搜索引擎都不来我这了,这就违背了我的初衷,这也为我后面改造博客埋下伏笔。

改造之路

经过一年的使用后,我渐渐觉得博客系统还是需要一定的访问量,不然不好意思说是博客系统,然后我就比对了一下Vue项目进行服务端渲染的方案,最终选定使用Nuxt改造。

确定以后,就可以上手了,我之前编写的代码中,很多页面的请求数据都是放在created()函数中,但是在Nuxt框架下,该函数会在客户端和服务端各执行一次,这不是我想要的,因此主要工作是将请求数据的代码放在了asyncData()函数中。

还好我之前写的前端都是按照模块化开发,很多功能都是按照组件来进行开发,如此一来,改造起来就快很多了。

还好我之前使用的是前后端分离模式,后端就只需要提供接口,改造起来,后端一行代码也不需要更改。

遇到的坑

虽然改造起来比较简单,但是有些代码也并不是一帆风顺,也到了很多坑,还好自己或多或少找到了解决方案。

  • 错误一:地址栏刷新/home的时候,后台控制台报 status 未定义,但是刷新

    /是可以的(我的之前代码逻辑是:输入/时候,路由直接跳转到/home

    解决方案:设置跨域代理,即先安装好axios:

    npm install @nuxtjs/axios -s
    

    接着在项目的根目录下中plugins中新建axios.js文件,输入以下内容:

    /*
     * @Author      : YaleXin
     * @Email       : me@yalexin.top
     * @LastEditors : YaleXin
     */
    import { Message } from "element-ui";
    import { MessageBox } from "element-ui";
    export default function ({store, route, redirect, $axios,req}) {
        // Error拦截器:出现错误的时候被调用,根据状态码做对应判断并显示全局Message
        $axios.onError((error) => {
          // console.log('erro statusr =', error.response.status);
          switch (parseInt(error.response.status)) {
            case 400: Message({
    					showClose: true,
    					message: '发送数据错误',
    					type: "error"
            });
              break;
            case 402: Message({
    					showClose: true,
    					message: '江湖中查无此人!',
    					type: "error"
            });
              break;
              // 密码错误
    				case 403: Message({
    					showClose: true,
    					message: '密令错误!',
    					type: "error"
    				});
    					break;
                // 密码错误
    				case 405: Message({
    					showClose: true,
    					message: '口令错误!',
    					type: "error"
    				});
    					break;
    				case 480: // 未登录
              console.log('480!!');
              redirect(redirectURL(route,req))
    					break;
    				case 500: Message({
    					showClose: true,
    					message: '后端出错',
    					type: "error"
    				}); break;
    			}
        })
        // Response拦截器:对正常返回的数据进行处理
        $axios.onResponse((response) => {
          return response.data 
        })
      }
    
    // 获取重定向地址
    const redirectURL = (route,req) => {
      // 客户端
      if(process.client) {
          return '/admin/login'
      } else{
        return '/admin/login'
      }
    
    }
    

    然后在nuxt.config.js中配置axios

      plugins: [
        {
          src: '~/plugins/axios',
          'ssr': true // 服务端渲染
       },
      buildModules: [
        '@nuxtjs/axios',
      ],
      modules: [
        '@nuxtjs/axios',
        '@nuxtjs/proxy',
      ],
      axios: {
        // Workaround to avoid enforcing hard-coded localhost:3000: https://github.com/nuxt-community/axios-module/issues/308
        proxy: true, // 开启跨域行为
        prefix: '/api', // 配置基本得url地址
        credentials: true
      },
          // 配置代理
      proxy: {
        '/api': {
            target: 'http://localhost:8080/api/',
            ws: false,
            changeOrigin: true,
            pathRewrite: {
                '^/api': '',
            }
        },
    	},
    
  • 我的项目中用了echarts,但是我就仅仅用来热力图组件,不想把整个echarts项目安装进我的项目,就想着怎么按需引入。后来在某个地方找到官方定制的网站,在上面的网站选后组件以后,直接下载js文件,然后就按照文档教程,在需要引入的地方引入:

    // .vue 文件中:
    <script>
    import echarts from "~/assets/js/echarts.min.js";
    
    export default {
        mounted(){
            echarts.init(...);
        }
    }
    
    </script>
    
  • 有的时候node服务端报window is not defined

    解决方案:有些代码会在服务端和客户端中都执行一遍,但是在服务端中,是没有window这个对象的,因此要在代码中加一个判断是在哪个端的语句:

    // 如果是客户端
     if (process.client) {
    
    }
    
  • 在组件中引用自定义的css文件总是失效。

    解决方法:原先按照vue的方式,引用方式为:

    @import "~/assets/css/blog.css"
    

    这个方法似乎在Nuxt框架下不行,要换成以下方式引用:

    <script>
        export default {
            head(){
        		return{
          			link: [
            			{rel: 'stylesheet', href: 									require('~/assets/css/blog.css')}
          			]
        		}
      		},
        }
    </script>
    

    总结

    总得来说,改造起来困难不是很大,加上vue的生态的确很好,很多问题都可以找得到解决方案,目前改造后的系统:

  • 支持页面动画,改善用户体验

  • 全站的站内链接均使用nuxt-link方式,加快页面切换以及避免相同路由切换时报错,而且还有利于SEO

  • 后台登陆支持验证码,增加安全性,之前的是输入正确的用户名和密码以后就可以登录了,安全性不是很大(虽然验证码也没有加多少安全性

  • 后台markdown解析增加高亮语法、删除线语法,就是这样子,这个插件官方没有,应该是太简单做了,我对照着原有的插件就做出来了。

  • 支持公式:如这是西塔$\theta$,下面是公式 $$ y=\sum_{i=0}^{n}x_i $$

未来可能进一步完善的方向:

  • 恢复文章下的评论组件,为什么叫恢复呢,因为之前的是支持的,但是我改造以后,回复按钮的绑定事件一直不触发,当时调了一天都没有调出来,调到自闭。
  • 支持夜间模式,这个好像挺难的,不好实现,有可能最终不实现了,哈哈哈哈哈哈哈哈哈。

2022.5.13 更新

  • 夜间模式

2022.6.5 更新

  • 恢复文章下的评论组件

2022.12.2 更新

  • 增加网站变灰功能

2023.6.19 更新

  • 将验证码方式修改为PoW

2023.9.1 更新

  • 优化归档页面:按年份展示

2023.9.29 更新

  • 支持docker

2023.12.15 更新

  • 添加置顶功能
历史评论
开始评论