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 ."
  },

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM