• nuxt + ts +vue简单后台项目,记录一些在做的过程中遇到的问题。


    一、nuxt框架是一个前端框架,这个框架我的理解就是有利于seo,就是在被人百度的时候,会优先搜索到这个框架的网站。

    二、主要问题:

    1.登录

    主要是在页面要先进行一些验证,数据请求的时候,必须携带正确的token才能请求数据,于是涉及到token的保存,需要通过接口获取到用户信息和token,再保存在store中,因为刷新页面,store就清空了,我就采用了localStorage保存信息。在localStorage中保存的只能在mounted中获取window对象,所以可能会有渲染延迟的现象,官方有个nuxt自带的nuxtServerInit方法,试了很久都不知道怎使用,我就暂时没有用。

    首先是在page/login.vue获取用户信息和token

    export default class AdminLogin extends Vue {
      private name: string = 'admin'
      private password: string = 'admin'
    
      // 登录
      private userLogin () {
        const data: object = {
          name: this.name,
          password: Md5.hashStr(this.password)
        };
        this.$axios.post('/api/v1/login', data).then((res: any) => {
          if (res.success) {
            this.$store.commit('SET_TOKEN', res.data.token);
            this.$store.commit('SET_USERINFO', { name: res.data.name });
            window.localStorage.setItem('unserAllInfo', JSON.stringify(res.data));
            this.$router.push('/admin/'); // 跳转
          } else {
            this.$message.error({ message: '登录失败,请输入正确的用户名和密码' });
          }
        });
      }
    }

    store/index.js

    import Vuex from 'vuex';
    
    const store = () => new Vuex.Store({
      state: {
        userInfo: {},
        token: ''
      },
      mutations: {
        SET_TOKEN (state, data) {
          state.token = data || '';
        },
        SET_USERINFO (state, data) {
          state.userInfo = data || {};
        }
      },
      actions: {
        // nuxtServerInit ({ commit }, { req }) {
        //   const cookie = req.headers.cookie;
        // }
      },
      getters: {
        token: (state) => {
          return state.token;
        },
        getuserInfo: (state) => {
          return state.userInfo;
        }
      }
    });
    
    export default store;

    在layout/admin.vue下面使用,防止刷新的时候store数据清空

    private async mounted () {
          // 设置登录和token信息,防止刷新的时候store清空
          const userInfo = window.localStorage.getItem('unserAllInfo') || null;
          if (userInfo) {
            const data = JSON.parse(userInfo);
            this.$store.commit('SET_TOKEN', data.token);
            this.$store.commit('SET_USERINFO', data);
          } else {
            this.$router.push('/admin/login');
          }
        }

    使用$store.getters.getuserInfo.name 可获取信息

    如果要退出登录,清空localStorage即可

    // 退出登录
        // GoOut() {
        //   window.localStorage.setItem('wmMonitorUsers', '')
        //   this.$router.push('/admin/login')
        // }

    在登录完成以后,我们每次发起数据请求的时候就需要带上token,于是在plugins下面对axios的请求进行了封装axios.js,需要在配置里面全局引用一下,在nuxt.config.js下加入以下代码

    plugins: [
        { src: '@/plugins/axios' },
      ]

    在plugins/axios.js写如下内容,都是抄的其他大神的。

    export default function ({ $axios, redirect, store }) {
      // http request 拦截器
      $axios.interceptors.request.use(
        (config) => {
          if (store.getters.token) {
            config.headers.Authorization = 'Bearer ' + store.getters.token;
          } else {
            config.headers.Authorization = '';
          }
          return config;
        },
        (err) => {
          return Promise.reject(err);
        });
    
      // http response 拦截器
      $axios.interceptors.response.use(
        (response) => {
          // 直接返回内容
          if (response.success) {
            return response.data;
          }
          return response.data;
        },
        (error) => {
          // store.commit(types.SET_LOAD, false);
          if (error.response) {
            const code = parseInt(error.response && error.response.status);
            switch (code) {
              case 401:
                sessionStorage.clear();
                redirect('/admin/login');
                console.log(401);
                break;
              case 403:
                sessionStorage.clear();
                redirect('/admin/login');
                console.log(403);
                break;
              case 404:
                sessionStorage.clear();
                console.log(404);
                break;
              case 500:
                // Message.error('Server exception');
                break;
              case 502:
                // Message.error('Bad Gateway');
                break;
              case 503:
                // Message.error(error.message);
                break;
              case 504:
                // Message.error(error.message);
                break;
              default:
                break;
            }
          }
          // console.error(error.config.url, error.response.status)
          return Promise.reject(error);
        });
    }

    接下来就是在页面,直接发起请求即可,为什么直接发起请求就可以了呢,因为我重新对axios进行了封装,在配置文件加载的时候就行了了这个操作,于是接下来在各个页面直接请求即可。

    例如在page下面的vue文件中发起请求:

    this.$axios.post('/api/v1/接口', { data: data }).then((res: any) => {
            if (res.success) {
              this.$message.success('保存成功!');
            } else {
              this.$message.error({ message: '保存失败!' });
            }
          });

    2.讲讲路由方面,我使用了<nuxt-link to="/admin/product"></nuxt-link>跳转,内容在<nuxt />中显示,跟vue的路由用起来一模一样。

    nuxt的路由很方便,就是page下面的vue页面的名字,相当于他自动给你配置了路由,而你直接使用地址跳转就可以。layout里面放的是布局文件,就是你框架的整体结构,比如你从layout里面的index要跳转到page下面的product.vue,只需在to后面加上/product即可。

    传参的路由,我要跳转到动态路由_id页面,我需要传参id过去,下面代码相当于admin/news/id,这个id是动态的,params是我传过去的id,跳转到的_id页面到时候路由显示就是admin/news/传过来的params里面的id

    文件结构

              <nuxt-link :to="{name:'admin-news-id', params:{id: item._id}}">{{ item.title }}</nuxt-link>

    动态路由_id页面里面获取id:this.$route.params.id,然后在根据id请求一些需要的数据

    3.配置文件nuxt.config.js,我主要是配置了这些。主要是对环境变量进行了配置,得到一个全局的服务器地址,比如,我要渲染从服务器拿到的图片或其他资源,我的写法是src=process.env.serverUrl + 服务器存数据的地址,例如'/public/img/a.img',这样就可以渲染出服务器上的图片了。

    const env = require('./env');
    
    module.exports = {
      mode: 'universal',
      /*
        ** Headers of the page
        ** ak=>百度地图
        */
      head: {
        title: '',
        meta: [
          { charset: 'utf-8' },
          { name: 'viewport', content: 'width=device-width, initial-scale=1' },
          { hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
        ],
        link: [
          { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
        ],
        script: [
          { src: '/rem.js', type: 'text/javascript', charset: 'utf-8' }
          // { src: '/ueditor_node/ueditor.config.js', type: 'text/javascript', charset: 'utf-8' },
          // { src: '/ueditor_node/ueditor.all.js', type: 'text/javascript', charset: 'utf-8' },
          // { src: '/ueditor.parse.min.js', type: 'text/javascript', charset: 'utf-8' },
          // { src: '/ueditor_node/lang/zh-cn/zh-cn.js', type: 'text/javascript', charset: 'utf-8' }
        ]
      },
      /*
        ** Customize the progress-bar color
        */
      loading: { color: '#fff' },
      /*
        ** Global CSS
        */
      css: [
        'element-ui/lib/theme-chalk/index.css',
        '~assets/css/basic.css',
        'quill/dist/quill.snow.css',
        'quill/dist/quill.bubble.css',
        'quill/dist/quill.core.css'
      ],
      /*
        ** Plugins to load before mounting the App
        */
      plugins: [
        '@/plugins/element-ui',
        '~/plugins/vue-echarts',
        '~/plugins/awe-dnd',
        { src: '@/plugins/vue-quill-editor', ssr: false },
        { src: '@/plugins/axios' },
        { src: '@/plugins/gmap' }
      ],
      /*
        ** Nuxt.js dev-modules
        */
      buildModules: ['@nuxt/typescript-build'],
      /*
        ** Nuxt.js modules
        */
      modules: [
        // Doc: https://axios.nuxtjs.org/usage
        '@nuxtjs/axios',
        ['@nuxtjs/proxy', { pathRewrite: { '^/api': '/' } }]
      ],
      proxy: {
        '/api': {
          target: env[process.env.NODE_ENV].ENV_API, // 目标接口域名
          changeOrigin: true, // 表示是否跨域
          pathRewrite: {
            '^/api': '' // 把 /api 替换成‘’
          }
        }
      },
      /*
        ** Axios module configuration
        ** See https://axios.nuxtjs.org/options
        */
      axios: {
        // See https://github.com/nuxt-community/axios-module#options
        proxy: true, // 表示开启代理
        prefix: '/api', // 表示给请求url加个前缀 /api
        credentials: true // 表示跨域请求时是否需要使用凭证
      },
      /*
        ** Build configuration
        */
      env: {
        serverUrl: env[process.env.NODE_ENV].ENV_API
      },
      build: {
        transpile: [/^element-ui/],
        /*
            ** You can extend webpack config here
            */
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        extend (config, ctx) {
        }
      }
    };

    env.js,开发环境和生产环境对应的接口

    module.exports = {
      dev: {
        NODE_ENV: 'dev',
        ENV_API: 'http://172.16.5.248:7001' // 测试服务器地址
      },
      pro: {
        NODE_ENV: 'pro',
        ENV_API: 'http://172.16.5.248:7001' // 正式服务器地址
      }
    }
    ;

    package.json下面的script修改了一下,主要是对环境变量的配置

    "scripts": {
        "dev": "cross-env NODE_ENV=dev nuxt",
        "start": "cross-env NODE_ENV=pro nuxt start",
        "build": "cross-env NODE_ENV=pro nuxt build",
        "test": "cross-env NODE_ENV=pro nuxt generate",
        "generate": "cross-env NODE_ENV=pro nuxt generate",   
        "prod": "cross-env NODE_ENV=pro node server/index.js",
        "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
      },
  • 相关阅读:
    账户管理命令 useradd、groupadd
    项目估算与计划不是一般的难!(1)——从建筑工程说起
    图的存储
    "Storage Virtualization" VS "Software-Defined Storage"
    项目代码风格要求
    struts2入门程序
    poj 3422 (费用流)
    项目估算与计划不是一般的难!(2)——估算要估啥?
    HDU1700:Points on Cycle
    数据结构 邻接矩阵深度及广度优先
  • 原文地址:https://www.cnblogs.com/wgl0126/p/12516709.html
Copyright © 2020-2023  润新知