带你撸vue后台,个人总结

294 阅读2分钟

文件结构化

api和views

api文件和views目录下的名称和api需求应该是对应的,这样会非常清晰

components

src下的components目录放置共用的组件,页面内的组件应该放在自己的目录下

Vuex

一个比较庞大的项目,几十个业务模块,几十种权限,但业务之间的耦合度是很低的,文章模块和评论模块几乎是俩个独立的东西,所以根本没有必要使用 vuex 来存储data,每个页面里存放自己的 data 就行。当然有些数据还是需要用 vuex 来统一管理的,如登录token,用户信息,或者是一些全局个人偏好设置等,还是用vuex管理更加的方便,具体当然还是要结合自己的业务场景的。 参考该的如何自动化项目

Module-Vuex

项目庞大起来,vuex也区分开了多个文件,就很容易搞混某个目录,声明的变量和方法等等,在文件export的时候加上namespaced: true在使用时就可以使用目录的方式引入this.$store.dispatch('app/getToken')前期是要做好vuex的配置

alias

路径别名,当项目逐渐变大之后,文件与文件之间的引用关系会很复杂,这时候就需要使用alias了。有的人喜欢alias指向src目录下,再使用相对路径找文件

const path = require('path');//使用node的path
//__dirname为根目录,join()为拼接参数,返回地址
resolve: {
  alias: {
     '@': path.join(__dirname,'src')
  }
}

//使用时
import stickTop from '@/comment/components/stickTop';

或者也可以

alias: {
  'src': path.join(__dirname, 'src'),
  'components': path.join(__dirname, 'src/components'),
  'api': path.join(__dirname, 'src/api'),
  'utils': path.join(__dirname, 'src/utils'),
  'store': path.join(__dirname, 'src/store'),
  'router': path.join(__dirname, 'src/router')
}

//使用时
import stickTop from 'components/stickTop'
import getArticle from 'api/article'

没有好与坏对与错,纯看个人喜好和团队规范。

ESLint

首先商店里安装eslint

代码规范检查,进入vsCode设置入口(文件>首选项>设置>用户设置>更多设置(右边的三个小点)>打开settings.json)然后在右边覆盖默认设置填写(配置一些基本的eslint的检测修复,深入自行查看配置)

    "files.autoSave":"off",
    "eslint.validate": [
     "javascript",
     "javascriptreact",
     "html",
     {
      "language": "vue",
      "autoFix": true
     }
    ],
    "eslint.options": {
        "plugins": ["html"]
    },

封装axios

import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// 创建axios实例
const service = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 5000 // 请求超时时间
})

// request拦截器
service.interceptors.request.use(config => {
  // Do something before request is sent
  if (store.getters.token) {
    config.headers['X-Token'] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
  }
  return config
}, error => {
  // Do something with request error
  console.log(error) // for debug
  Promise.reject(error)
})

// respone拦截器
service.interceptors.response.use(
  response => response,
  /**
  * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
  * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
  */
  //  const res = response.data;
  //     if (res.code !== 20000) {
  //       Message({
  //         message: res.message,
  //         type: 'error',
  //         duration: 5 * 1000
  //       });
  //       // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
  //       if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  //         MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
  //           confirmButtonText: '重新登录',
  //           cancelButtonText: '取消',
  //           type: 'warning'
  //         }).then(() => {
  //           store.dispatch('FedLogOut').then(() => {
  //             location.reload();// 为了重新实例化vue-router对象 避免bug
  //           });
  //         })
  //       }
  //       return Promise.reject('error');
  //     } else {
  //       return response.data;
  //     }
  error => {
    console.log('err' + error)// for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  })

export default service


import request from '@/utils/request'

//使用
export function getInfo(params) {
  return request({
    url: '/user/info',
    method: 'get',
    params
  });
}

比如后台项目,每一个请求都是要带 token 来验证权限的,这样封装以下的话我们就不用每个请求都手动来塞 token,或者来做一些统一的异常处理,一劳永逸。 (拦截器用上回来补充)

前后端交互

环境变量

vue-cli3的环境变量查阅文档

根目录下包含了.env.development.nev.production文件,代表了开发环境变量和线上环境变量,可在任何地方调用 process.env.**号代表你声明的环境变量名

//.env.development
VUE_APP_BASE_API = '/dev'
//use
const pri = process.env.VUE_APP_BASE_API;
//输出/dev

跨域问题

前端开发环境处理跨域问题主要用到域名代理:

即定义一个开发环境关键字段,请求时把字段代理到对应的域名上,实际看到的请求地址是本域的。

//vue.config.js
module.exports={
	//...其他配置
    devServer:{
    	//...
        proxy: {
          [process.env.VUE_APP_BASE_API]: {
            target: `http://192.168.1.11:8443`,//将/dev代理到的域名
            changeOrigin: true,
            pathRewrite: {
                  ['^' + process.env.VUE_APP_BASE_API]: ''//代理后的地址把/dev改为空,进行请求
            }
          }
        },
    }
}

process.env.VUE_APP_BASE_API是vueCli的环境配置变量

线上的跨域问题一般都是后台解决,搭建反向代理什么的,前端很难解决跨域问题。

自行mock

用mockjs默认后台数据

router-view

我创建和编辑的页面使用的是同一个component,默认情况下当这两个页面切换时并不会触发vue的created或者mounted钩子,官方说你可以通过watch $route的变化来做处理,但其实说真的还是蛮麻烦的。后来发现其实可以简单的在 router-view上加上一个唯一的key,来保证路由切换时都会重新渲染触发钩子了。这样简单的多了。 router-viewcomponent :is的用法有相似的地方,区别在这

<router-view :key="key"></router-view>

computed: {
    key() {
        return this.$route.name !== undefined? this.$route.name + +new Date(): this.$route + +new Date()
    }
 }

优化

自动化项目

webpack有一个自动化项目的配置,还是挺好用的叫require.context可自行查询文档。

自动引入文件夹内的所有文件,不必每增加一个文件去inport一次

这个项目内在vuex中使用,每个模块有自己的vuex文件,在配置vuex里,引入:

const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = {}
//modulesFiles.keys()拿到文件名数组
modulesFiles.keys().map(item => {
  const moduleName = item.replace(/^\.\/(.*)\.\w+$/, '$1');//格式化文件名,用于做对象key
  const value = modulesFiles(item);//根据目录名,取文件内容
  modules[moduleName] = value.default;//赋值给对象
})

const store = new Vuex.Store({
  modules,//引入,{a:a文件内容,b:b文件内容}
  getters
})

export default store

require.context参考文档

多环境

vue-cli 默认只提供了devprod两种环境。但其实正真的开发流程可能还会多一个sit或者stage环境,就是所谓的测试环境和预发布环境。所以我们就要简单的修改一下代码。其实很简单就是设置不同的环境变量

"build:prod": "NODE_ENV=production node build/build.js",
"build:sit": "NODE_ENV=sit node build/build.js",

普通打包

npm install
npm run build:prod

优化以来打包,npm依赖打入基础淘宝镜像进行加速

npm install --registry=https://registry.npm.taobao.org
npm run build:prod

放上基础篇链接:手摸手,带你用vue撸后台 系列一(基础篇)