Vue开发总结 及 一些最佳实践 (已更新)

4,865 阅读3分钟

基本开发环境

vue-cli3 创建的项目,vscode 作为代码编写工具 vscode插件推荐:vscode 插件配置

文章目录

  1. 项目目录结构介绍
  2. UI 框架选择
  3. main,js 处理
  4. axios 请求二次封装

1. 项目目录结构简介

├── public // index.html
├── src // 业务相关
│ ├── assets // 静态文件(css, images)
│ ├── components // 全局组件
│ ├── layouts // 基础样式布局
│ ├── plugin // 样式及工具引入
│ ├── request // 请求配置
│ ├── router // 路由
│ ├── store // 全局状态管理
│ ├── utils // 工具文件
│ ├── app.vue // 入口文件
│ ├── main.js // 主要配置文件
│ └── views // 页面
├── .eslintrc.js // eslint 检查配置
├── .env.release // 测试环境变量
├── .env.pre-build // 预发环境变量
└── vue.config.js // webpack 打包配置

2. UI 框架选择

经框架选择验证对比 element,iview,ant-design-vue 最终选择 ant-design-vue,传送门 vue.ant.design/docs/vue/in…

优点:
  1. 好看
  2. 文档清晰
  3. 使用方便,示例清晰
  4. bug少,组件使用顺滑
  5. 性能较好,有单例测试

3. main.js 分散处理

main.js 作为操作入口,很多东西需要引入,代码体积过大,需要进行优化,逻辑清晰,方便文虎

1. 处理三方框架

新建一个文件夹 plugin,存放所有需要引入的 main.js 挂载的组件、方法、第三方库

  1. ant-design.js 按照官方推荐,按需引入 优点: 我们开发项目不一定能使用到所有的组件,这样引入减小项目体积

    import Vue from 'vue'
    import {
      ConfigProvider,
      Pagination,
      Steps,
      Cascader,
      Row,
      Col,
      Table
    } from 'ant-design-vue'
    import 'ant-design-vue/dist/antd.less'
    
    Vue.use(ConfigProvider)
    Vue.use(Steps)
    Vue.use(Cascader)
    Vue.use(Row)
    Vue.use(Col)
    Vue.use(Table)
    
  2. func.js 自定义的一些方法,挂到 vue 原型上

    import Vue from 'vue'
    import api from '@/request/api'
    import { isInvalid, isValid } from '@/utils/verify'
    // 请求接口
    Vue.prototype.$api = api
    // 验证工具
    Vue.prototype.$isInvalid = isInvalid
    Vue.prototype.$isValid = isValid
    

    这样,分散几个文件,然后将他们统一引入到 index.js

    import './ant-design.js'
    import './func.js'
    import './moment'
    

    最后放入 main.js,整个世界都清晰简单了 import './plugin'

    2. 全局引入自定义组件

    收到评论区大神提醒,研究了一下 webpack 中的 require.context

    require.contextwebpack 中,用来创建自己的(模块)上下文

    webpack 会在构建的时候解析代码中的 require.context()

    require.context(directory, useSubdirectories = false, regExp = /^/) 函数接收三个参数:

    要搜索的文件夹目录 是否还应该搜索它的子目录 以及一个匹配文件的正则表达式

    // 语法
    require.context(directory, useSubdirectories = false, regExp = /^\.\//);
    // 示例
    require.context('./test', false, /\.test\.js$/);
    

    所以,在 main.js 中,直接可以注册我所有的自定义组件,非常简单

    // 自定义组件
    const requireComponents = require.context('@v/components', true, /\.vue$/)
    // 打印结果
    // 遍历出每个组件的路径
    requireComponents.keys().map(fileName => {
      // 获取组件配置
      const componentConfig = requireComponents(fileName)
      // 剥去文件名开头的 `./` 和`.vue`结尾的扩展名
      const componentName = fileName.replace(/^\.\//, '').replace(/\.vue$/, '')
      // 全局注册组件
      Vue.component(
        componentName.replace(/\//, '-'),
        // 如果这个组件选项是通过 `export default` 导出的,那么就会优先使用 `.default`,否则回退到使用模块的根。
        componentConfig.default || componentConfig
      )
    })
    

4. axios 请求二次封装

axios 不过多介绍,上干货

  1. 新建文件 axios

  2. 请求拦截器 根据自己业务需求,修改请求头以及超时时间等

    import axios from 'axios'
    axios.interceptors.request.use(
      config => {
        // 判断是否是提交文件,还是常规请求
        if (config.data instanceof FormData) {
          config.headers = {
            'Content-Type': 'multipart/form-data' // 此处格式自定义
          }
        } else {
          config.data = JSON.stringify(config.data)
          config.headers = {
            'Content-Type': 'application/json', // 此处格式自定义
            token: getLocalStorage('token')
          }
        }
        config.withCredentials = true
        config.timeout = 5000    // 超时时间
        return config
      },
      error => {
        return Promise.reject(error)
      }
    )
    
  3. 响应拦截器 根据后台返回数据,做些统一处理

    // 添加响应拦截器
    axios.interceptors.response.use(
      res => {
        let data = res.data
        if (res.statusCode !== 200) {
          if (data.failureReason === 4011 || data.failureReason === 4012) {
            console.log('需要重新登录')
          }
        } else {
          if (data.resultStates === 0) {
            return data
          } else {
            return Promise.reject(data)
          }
        }
      },
      error => {
        notification['error']({
          message: '提示',
          duration: 2,
          description: '后台报错'
        })
        // 对响应错误做点什么
        return Promise.reject(error)
      }
    )
    
  4. 封装get,post,并导出

    export function get (url, params = {}) {
      return new Promise((resolve, reject) => {
        axios
          .get(url, {
            params: params
          })
          .then(response => {
            if (response.success) {
              resolve(response.data)
            }
          })
          .catch(err => {
            reject(err)
          })
      })
    }
    
    /**
     * 封装post请求
     * @param url
     * @param data
     * @returns {Promise}
     */
    export function post (url, data = {}) {
      return new Promise((resolve, reject) => {
        axios.post(url, data).then(
          response => {
            if (response.success) {
              resolve(response.data)
            }
          },
          err => {
            reject(err)
          }
        )
      })
    }
    
  5. 重点:新建 api.js 文件 将后台请求接口全部写在此处,统一管理

    import { get, post } from './axios'
    const api = {
         reqLogin: p => post('api/user/addFormId', p),
          reqGetInfo: p => post('api/user/addFormId', p)
    }
    export default api
    
    // 将 api 引入到 main.js 中
    Vue.prototype.$api = api
    
    // 这样页面中使用
    this.$api.reqLogin().then(res => {
          console.log(res)
    })
    

是不是非常方便?鼓掌 啪啪啪啪......

web 前端群招人,有梦想的一群小青年 www.jianshu.com/p/33eee1c26…