Vue-Cli 项目基础搭建

写在开头的开头

目标搭建一个Vue Cli 中后台项目的基础。一步一步搭建,众多知识点已经有很多文字,这里会综合比较多的连接。接触的点会多,但是篇幅,不希望太大。
学习的时候,希望多翻阅文档,资料地址也会引入到原文

资料

后台可能是这样的以 iview-admin 为栗子在线 Demo

拆解(结合将要做的做一个iView 拆解)

  • 侧边栏菜单权限过滤,这部分实现需要配合路由,权限数据保存,跨组件通信(iview 使用了vuex)
  • 标签页,这部分也需要吧打开的页面使用数据存起来,也搭配 keep-alive 附录中的 VUE 9个性能优化秘密?(vue-9-perf-secrets) 其中之一优化办法就是 keep-alive

将要做什么

@vue/cli 创建项目

开发环境:
+ Win10 x64
+ node v10.15.3
+ npm v6.4.1
+ @vue/cli 3.6.3
复制代码
vue create project-name
复制代码

缩减篇幅,省略具体创建过程。

  1. step.1 选择设置,默认设置或者自定义Manually
  1. step.2 自定义配置,有 TypeScript支持,也有PWA。
  1. step.3 路由模式选择 history
  1. step.4 CSS 编译器选择
  1. step.5 ESLint 以及配置选择
  1. step.6 何时检查 Lint
  1. step.7 ESLint 配置文件写在哪里,可以单独文件,也可以在package.json
  1. step.8 是否保存配置信息,下次项目使用 N
  2. 自动安装依赖
目录规划
.
├── build  项目构建配置
├── public  打包所需静态资源
└── src
    ├── api  AJAX请求
    └── assets  项目静态资源
        ├── icons  SVG 图标资源
        ├── fonts  字体图标资源
        └── images  图片资源
    ├── components  业务组件
    ├── config  项目运行配置
    ├── directive  自定义指令
    ├── libs  封装工具函数
    ├── router  路由配置
    ├── store  Vuex配置
    └── views  页面文件
复制代码

字体库 && SVG

main.js 引入全局 阿里 Ant 图标字体库

SVG

图标字体,也可以用SVG代替,方案可以做一个SVG组件,通过名字,载入不同的 SVG图标,通过size,控制图标大小,color,控制颜色即可


网络请求 axios封装api

给axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示) iview-admin axios 用继承封装。当中亮点,对请求队列做了处理,多次请求同一个地址,会节流。

// 安装
npm i axios
复制代码
  • 统一捕获接口报错 : 用的axios内置的拦截器
  • 弹窗提示: 引入 Element UI的Message组件
  • 报错重定向: 路由钩子
  • 基础鉴权: 服务端过期时间戳和token,还有借助路由的钩子
  • 客户端支持防止 CSRF/XSRF
  • 表单序列化: 我这边直接用qs(npm模块),你有时间也可以自己写
  • 号外,对请求队列优化,尤其是翻页时多次请求。(未完成)

请求拦截器 Axios.interceptors.request

带上自己需要的参数,比如CSRF/XSRF,基础鉴权 token,请求时间戳
对请求数据做处理,转表单,或转Json
对错误的情况统一处理

响应拦截器 Axios.interceptors.interceptors

对响应结果统一处理,响应结果状态status 判断解封装,错误处理等

axios可配置

iview-admin libs/axios.js

import axios from 'axios'
import store from '@/store'
// import { Spin } from 'iview'
const addErrorLog = errorInfo => {
  const { statusText, status, request: { responseURL } } = errorInfo
  let info = {
    type: 'ajax',
    code: status,
    mes: statusText,
    url: responseURL
  }
  if (!responseURL.includes('save_error_logger')) store.dispatch('addErrorLog', info)
}

class HttpRequest {
  constructor (baseUrl = baseURL) {
    this.baseUrl = baseUrl
    this.queue = {}
  }
  getInsideConfig () {
    const config = {
      baseURL: this.baseUrl,
      headers: {
        //
      }
    }
    return config
  }
  destroy (url) {
    delete this.queue[url]
    if (!Object.keys(this.queue).length) {
      // Spin.hide()
    }
  }
  interceptors (instance, url) {
    // 请求拦截
    instance.interceptors.request.use(config => {
      // 添加全局的loading...
      if (!Object.keys(this.queue).length) {
        // Spin.show() // 不建议开启,因为界面不友好
      }
      this.queue[url] = true
      return config
    }, error => {
      return Promise.reject(error)
    })
    // 响应拦截
    instance.interceptors.response.use(res => {
      this.destroy(url)
      const { data, status } = res
      return { data, status }
    }, error => {
      this.destroy(url)
      let errorInfo = error.response
      if (!errorInfo) {
        const { request: { statusText, status }, config } = JSON.parse(JSON.stringify(error))
        errorInfo = {
          statusText,
          status,
          request: { responseURL: config.url }
        }
      }
      addErrorLog(errorInfo)
      return Promise.reject(error)
    })
  }
  request (options) {
    const instance = axios.create()
    options = Object.assign(this.getInsideConfig(), options)
    this.interceptors(instance, options.url)
    return instance(options)
  }
}
export default HttpRequest


复制代码

Vuex 数据管理

面试通常都会被问到,数据通信的问题,跨组件之间如何实现数据管理。

当然方法不止 vuex ,

  • props
  • provide / inject
  • 本地存储Local Storage,Cookies 也可以实现。
  • vuex,项目比较简单时,store 都在一个文件中,或者 getter,actions,mutations,mutations-types,state拆分。应用比较大的时候,可以按模块拆分。

扩展阅读

没有废话的vue高级进阶( 二 ) 8种组件通信详解

import Vue from 'vue'
import Vuex from 'vuex'
// 按模块拆分
import app from './module/app'
// 打开 vuex logs
import createLogger from 'vuex/dist/logger'

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production'

export default new Vuex.Store({
  state: {

  },
  mutations: {

  },
  actions: {

  },
  // 按模块引入
  modules: {
    app
  },
  strict: debug,
  plugins: debug ? [createLogger()] : []
})
复制代码

Vue Router. 做好路由守卫

包含的功能:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

高级进阶

  • 导航守卫
  • 路由元信息
  • 过度动效
  • 数据获取
  • 滚动行为
  • 路由懒加载

我们可以做什么

  • 嵌套路由/视图表,子路由 children 可以更好的组织页面
  • 路由参数,跳转,传参,匹配
  • 过渡效果,滚动行为
  • 导航守卫,权限限定
  • 路由懒加载,结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载
  • 判断用户是否已经登录,控制进入权限页面。
  • 定义路由的时候可以配置 meta 字段,个性化定制一些功能
  • 等等

全局前置守卫

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // todo 在路由守卫中,可以判断用户登录情况,鉴权,
})
复制代码

菜单栏权限过滤

iview-admin 中侧边菜单栏权限,是在 router meta增加一个字段,

流程

  • vuex 搭配使用 vuex-persistedstate vuex 数据持久化
  • 1.用户登录后,获取用户权限,权限列表(列表必须能和,router meta 字段对比)
  • 2.提交用户数据,权限等到 Vuex(数据中心)
  • 3.用户权限和 router meta 生成权限列表,提交到vuex
  • 4.菜单栏页面,getter 到数据变化,更新菜单栏
  • 5.注意:思考是否需要,数据需要本地化一份,在用户刷新页面,或者vuex(数据中心)数据丢失时,还要能拿到用户权限,token等数据。

vue.config.js

Vue CLI.

调整 webpack 配置最简单的方式就是在 vue.config.js 中的 configureWebpack 选项提供一个对象:

// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      new MyAwesomeWebpackPlugin()
    ]
  }
}
复制代码

该对象将会被 webpack-merge 合并入最终的 webpack 配置。

文档中,提及链式操作 (高级)、修改 Loader 选项、替换Loader、新建Loader、修改插件,等等。

环境变量和模式

NODE_ENV
如果在环境中有默认的 NODE_ENV,你应该移除它或在运行 vue-cli-service 命令的时候明确地设置 NODE_ENV。
模式

模式是 Vue CLI 项目中一个重要的概念。默认情况下,一个 Vue CLI 项目有三个模式:

  • development 模式用于 vue-cli-service serve
  • production 模式用于 vue-cli-service buildvue-cli-service test:e2e
  • test 模式用于 vue-cli-service test:unit

注意模式不同于 NODE_ENV,一个模式可以包含多个环境变量。也就是说,每个模式都会将 NODE_ENV 的值设置为模式的名称——比如在 development 模式下 NODE_ENV 的值会被设置为 "development"

你可以通过为 .env 文件增加后缀来设置某个模式下特有的环境变量。比如,如果你在项目根目录创建一个名为 .env.development 的文件,那么在这个文件里声明过的变量就只会在 development 模式下被载入。

你可以通过传递 --mode 选项参数为命令行覆写默认的模式。例如,如果你想要在构建命令中使用开发环境变量,请在你的 package.json 脚本中加入:

"dev-build": "vue-cli-service build --mode development",
复制代码
在客户端侧代码中使用环境变量

只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。你可以在应用的代码中这样访问它们:

console.log(process.env.VUE_APP_SECRET)
复制代码

vue.config.js

  • 有了 NODE_ENV 可以对不同环境做出不同的配置
  • 文件夹别名 resolve.alias
  • 设置代理 devServer,解决跨域开发问题
const path = require('path')
// Webpack包文件分析器
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

function resolve (dir) {
  return path.join(__dirname, './', dir)
}

// 项目部署基础 (webpack 的 devServer 地址)
// process.env.NODE_ENV
// 正式环境 production
// 开发环境 development
// 默认情况下,我们假设你的应用将被部署在域的根目录下,
// 例如:https://www.my-app.com/
// 默认:'/'
// 如果您的应用程序部署在子路径中,则需要在这指定子路径
// 例如:https://www.foobar.com/my-app/
// 需要将它改为'/my-app/'
const BASE_URL = process.env.NODE_ENV === 'production'
  ? '/my-app/'
  : '/'

module.exports = {
  // 这里是对环境的配置,不同环境对应不同的BASE_API,以便 axios 的请求地址不同 baseUrl 从 Vue CLI 3.3 起已弃用,请使用publicPath
  publicPath: BASE_URL,
  // tweak internal webpack configuration.
  // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
  // 如果你不需要使用eslint,把lintOnSave设为false即可
  lintOnSave: false,

  /**
   * 对内部的 webpack 配置进行更细粒度的修改
   * https://github.com/neutrinojs/webpack-chain see
   * https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
   * @param config
   */
  chainWebpack: (config) => {
    // key,value自行定义,比如.set('@@', resolve('src/components'))
    config.resolve.alias
      .set('@', resolve('src'))
      .set('api', resolve('src/api'))
      .set('common', resolve('src/common'))
      .set('components', resolve('src/components'))
  },
  /**
   * 调整 webpack 配置
   * https://cli.vuejs.org/zh/guide/webpack.html#%E7%AE%80%E5%8D%95%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F
   * @param config
   */
  configureWebpack: config => {
    // 生产and测试环境
    let pluginsPro = [
      // Webpack包文件分析器(https://github.com/webpack-contrib/webpack-bundle-analyzer)
      // new BundleAnalyzerPlugin()
    ]
    // 开发环境
    let pluginsDev = []
    if (process.env.NODE_ENV === 'production') {
      // 为生产环境修改配置... process.env.NODE_ENV !== 'development'
      config.plugins = [...config.plugins, ...pluginsPro]
    } else {
      // 为开发环境修改配置...
      config.plugins = [...config.plugins, ...pluginsDev]
    }
  },
  // 打包时不生成.map文件
  productionSourceMap: false,
  // webpack-dev-server 相关配置 https://webpack.js.org/configuration/dev-server/
  // 这里写你调用接口的基础路径,来解决跨域,如果设置了代理,那你本地开发环境的axios的baseUrl要写为 '' ,即空字符串
  // devServer: {
  //   proxy: 'localhost:3000'
  // }
  devServer: {
    // host: 'localhost',
    host: '0.0.0.0',
    port: 8000, // 端口号
    https: false, // https:{type:Boolean}
    open: true, // 配置自动启动浏览器
    hotOnly: true, // 热更新
    // 配置跨域处理,只有一个代理
    proxy: {
      '/my-app/*': {
        target: 'http://xxx.xxx.xxx.xxx:xxxx/',
        changeOrigin: true,
        pathRewrite: {
          '^/my-app': ''
        }
      },
      '/SocketWeb/*': {
        target: 'http://xxx.xxx.xxx.xxx:xxxx',
        changeOrigin: true,
        // websocket支持
        ws: true,
        secure: false
      }
    }
  }
}

复制代码
开发基础环境可以了,开发中遇到的文件夹别名,请求跨域的问题解决了,自定义配置,也可以更具自己公司的情况配置。还有比较自定义的部分可以参照文档配置。

webpack-bundle-analyzer

安装

$ npm intall webpack-bundle-analyzer --save-dev
复制代码
  1. 配置vue.config.js 打开注释 webpack-bundle-analyzer 的部分。
  2. 在script中添加
// 在运行 build 时,后台面添加  --report
npm run build --report
// 或者在script中添加新命令
"analyze": "npm_config_report=true npm run build"
复制代码

VUE 9个性能优化秘密?(vue-9-perf-secrets)

转载于:https://juejin.im/post/5cbeba395188250a845da19d

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值