Vue-Cli 项目基础搭建
栏目: JavaScript · 发布时间: 5年前
内容简介:目标搭建一个Vue Cli 中后台项目的基础。一步一步搭建,希望能有所收益。后台可能是这样的(参考 AdminLTE)
目标搭建一个Vue Cli 中后台项目的基础。一步一步搭建,希望能有所收益。
学习的时候,希望多翻阅文档,资料地址也会引入到原文
后台可能是这样的(参考 AdminLTE)
主要包含
- 侧边菜单 aside
- 右侧 container
- 头部 header
- 主体 main。页面主要变化的部分
资料
- Vue CLI .
- 源码 GitHub E-Admin .
将要做什么
- 开发环境 @vue/cli 创建项目
- 字体库 & SVG使用
- 网络请求 axios封装api
- 数据管理 vuex
- vue router 做好路由守卫
- 附录
- vue.config.js
- webpack-bundle-analyzer 使用
- VUE 9个性能优化秘密?(vue-9-perf-secrets)
@vue/cli 创建项目
开发环境: + Win10 x64 + node v10.15.3 + npm v6.4.1 + @vue/cli 3.6.3 复制代码
vue create project-name 复制代码
缩减篇幅,省略具体创建过程。
- step.1 选择设置,默认设置或者自定义Manually
- step.2 自定义配置,有 TypeScript支持,也有PWA。
- step.3 路由模式选择 history
- step.4 CSS 编译器选择
- step.5 ESLint 以及配置选择
- step.6 何时检查 Lint
- step.7 ESLint 配置文件写在哪里,可以单独文件,也可以在package.json
- step.8 是否保存配置信息,下次项目使用 N
- 自动安装依赖
目录规划
. ├── 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
// 安装 npm i axios 复制代码
- 统一捕获接口报错 : 用的axios内置的拦截器
- 弹窗提示: 引入 Element UI的Message组件
- 报错重定向: 路由钩子
- 基础鉴权: 服务端过期时间戳和token,还有借助路由的钩子
- 客户端支持防止 CSRF/XSRF
- 表单序列化: 我这边直接用qs(npm模块),你有时间也可以自己写
- 号外,对请求队列优化,尤其是翻页时多次请求。(未完成)
请求拦截器 Axios.interceptors.request
带上自己需要的参数,比如CSRF/XSRF,基础鉴权 token,请求时间戳
对请求数据做处理,转表单,或转Json
对错误的情况统一处理
响应拦截器 Axios.interceptors.interceptors
对响应结果统一处理,响应结果状态status 判断解封装,错误处理等
axios可配置
import axios from "axios"; import qs from "qs"; import { Message } from "element-ui"; import router from "../router"; const Axios = axios.create({ baseURL: "/", // 因为我本地做了反向代理 timeout: 10000, responseType: "json", withCredentials: true, // 是否允许带cookie这些 headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" } }); //POST传参序列化(添加请求拦截器) Axios.interceptors.request.use( config => { // 在发送请求之前做某件事 if ( config.method === "post" ) { // 序列化 若是能直接接受json 格式,可以不用 qs 来序列化的 config.data = qs.stringify(config.data); } // 若是有做鉴权token , 就给头部带上token // 若是需要跨站点,存放到 cookie 会好一点,限制也没那么多,有些浏览环境限制了 localstorage 的使用 // 这里localStorage一般是请求成功后我们自行写入到本地的,因为你放在vuex刷新就没了 // 一些必要的数据写入本地,优先从本地读取 if (localStorage.token) { config.headers.Authorization = localStorage.token; } return config; }, error => { // error 错误处理 Message({ // 饿了么的消息弹窗组件,类似toast showClose: true, message: error && error.data.error.message, type: 'error' }); return Promise.reject(error.data.error.message); } ); //返回状态判断(添加响应拦截器) Axios.interceptors.response.use( res => { //对响应数据做些事 if (res.data && !res.data.success) { Message({ // 饿了么的消息弹窗组件,类似toast showClose: true, message: res.data.error.message.message ? res.data.error.message.message : res.data.error.message, type: "error" }); return Promise.reject(res.data.error.message); } return res; }, error => { // 用户登录的时候会拿到一个基础信息,比如用户名,token,过期时间戳 // 直接丢localStorage或者sessionStorage if (!window.localStorage.getItem("loginUserBaseInfo")) { // 若是接口访问的时候没有发现有鉴权的基础信息,直接返回登录页 router.push({ path: "/login" }); } else { // 若是有基础信息的情况下,判断时间戳和当前的时间,若是当前的时间大于服务器过期的时间 // 乖乖的返回去登录页重新登录 let lifeTime = JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime * 1000; let nowTime = new Date().getTime(); // 当前时间的时间戳 console.log(nowTime, lifeTime); console.log(nowTime > lifeTime); if (nowTime > lifeTime) { Message({ showClose: true, message: "登录状态信息过期,请重新登录", type: "error" }); router.push({ path: "/login" }); } else { // 下面是接口回调的satus ,因为我做了一些错误页面,所以都会指向对应的报错页面 if (error.response.status === 403) { router.push({ path: "/error/403" }); } if (error.response.status === 500) { router.push({ path: "/error/500" }); } if (error.response.status === 502) { router.push({ path: "/error/502" }); } if (error.response.status === 404) { router.push({ path: "/error/404" }); } } } // 返回 response 里的错误信息 let errorInfo = error.data.error ? error.data.error.message : error.data; return Promise.reject(errorInfo); } ); export default Axios 复制代码
Vuex 数据管理
面试通常都会被问到,数据通信的问题,跨组件之间如何实现数据管理。当然方法不止 vuex
,本地存储Local Storage,Cookies 也可以实现。项目小的时候,可以不使用vuex,项目比较简单时,store 都在一个文件中,或者 getter,actions,mutations,mutations-types,state拆分。应用比较大的时候,可以按模块拆分。
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 meta
全局前置守卫
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // todo 在路由守卫中,可以判断用户登录情况,鉴权, }) 复制代码
侧边菜单栏配置
用户登录后,获取用户权限,比对 routers
提交一份数据到 vuex
根据用户权限更新数据,渲染菜单栏目
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
模式
模式是 Vue CLI 项目中一个重要的概念。默认情况下,一个 Vue CLI 项目有三个模式:
-
development
模式用于vue-cli-service serve
-
production
模式用于vue-cli-service build
和vue-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 } } } } 复制代码
开发基础环境可以了,开发中遇到的文件夹别名,请求跨域的问题解决了,自定义配置,也可以更具自己公司的情况配置。还有比较自定义的部分可以参照文档配置。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Hadoop 基础之搭建环境
- golang基础教程(一)、环境搭建
- MyBatis基础搭建及架构概述
- 搭建基础架构云的三利三弊
- Dubbo(一) —— 基础知识和项目搭建
- Hyperledger Fabric 2.0基础环境搭建
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
代码阅读方法与实践
斯平内利斯 / 赵学良 / 清华大学出版社 / 2004-03-01 / 45.00元
代码阅读有自身的一套技能,重要的是能够确定什么时候使用哪项技术。本书中,作者使用600多个现实的例子,向读者展示如何区分好的(和坏的)代码,如何阅读,应该注意什么,以及如何使用这些知识改进自己的代码。养成阅读高品质代码的习惯,可以提高编写代码的能力。 阅读代码是程序员的基本技能,同时也是软件开发、维护、演进、审查和重用过程中不可或缺的组成部分。本书首次将阅读代码作为一项独立课题......一起来看看 《代码阅读方法与实践》 这本书的介绍吧!