一. vue cli-webpack配置
1. 說明
在vue cli創建的項目中,配置文件為:vue.config.js
vue.config.js
是一個可選的配置文件,如果項目的 (和 package.json
同級的) 根目錄中存在這個文件,那么它會被 @vue/cli-service
自動加載。
2. vue cli 基本配置
(詳見:https://cli.vuejs.org/zh/config/#全局-cli-配置 )
(1). outputDir
(2). publicPath
剖析:
默認值為‘/’,生成的打包文件的引用的路徑都是以/開頭,沒法直接在vscode中運行,需要部署后才能運行,
如果改為'./',生成的打包文件的引用路徑如下圖,可以直接在vscode中運行
3. webpack配置
(詳見:https://cli.vuejs.org/zh/guide/webpack.html#簡單的配置方式 )
在vue cli創建的項目中,不能配置webpack.config.js文件,需要在vue.config.js中的configureWebpack 或 chainWebpack 屬性中配置, configureWebpack 屬性中的配置和webpack中的配置一樣,自動就合並了。
補充:cli中,@符號已經默認配置了,對應的就是src目錄,當然可以重寫。
下面是幾種寫法:
const path = require('path'); module.exports = { //CLI提供的屬性 outputDir: './build', // publicPath: './', //打包后的可以直接使用,不用發布,默認是 '/' // webpack寫法1(json格式) // 和webpack屬性完全一致, 最后會進行合並 configureWebpack: { resolve: { alias: { components: '@/components', }, }, }, // webpack寫法2(函數形式) // configureWebpack: (config) => { // config.resolve.alias = { // '@': path.resolve(__dirname, 'src'), // components: '@/components' // } // } // webpack寫法3(鏈式編程) // chainWebpack: (config) => { // config.resolve.alias // .set('@', path.resolve(__dirname, 'src')) // .set('components', '@/components'); // }, };
二. element-plus配置
1. 全局引用
(1). 說明
如果你對打包后的文件大小不是很在乎,那么使用完整導入會更方便。
(2). 步驟
A. 安裝生產依賴 【npm install element-plus】
B. 全局引用,在main.ts文件中導入
import { createApp } from 'vue'; import App from './App.vue'; // 全局引入element-plus import ElementPlus from 'element-plus'; import 'element-plus/dist/index.css'; const app = createApp(App); app.use(ElementPlus); //全局引用element-plus app.use(golbalRegister); // 按需引入element-plus app.mount('#app');
C. 在頁面中直接使用任意組件即可
<template> <div> <el-button>默認按鈕</el-button> <el-button type="primary">主要按鈕</el-button> <el-button type="success">成功按鈕</el-button> <el-button type="info">信息按鈕</el-button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ setup() { }, }); </script> <style lang="less"></style>
2. 按需引用
(1).說明
根據需要導入相應的組件和樣式
(2).步驟
直接在對應頁面導入組件和組件的樣式,使用即可
<template> <div> <el-button>默認按鈕</el-button> <el-button type="primary">主要按鈕</el-button> <el-button type="success">成功按鈕</el-button> <el-button type="info">信息按鈕</el-button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import { ElButton } from 'element-plus'; import 'element-plus/theme-chalk/el-button.css'; export default defineComponent({ components: { ElButton, }, setup() { }, }); </script> <style lang="less"></style>
3. 按需引用-全局封裝
(1). 說明
上述在每個頁面導入組件和組件的樣式過於繁瑣,所以這里將element-plus的組件封裝成全局,然后每個頁面直接使用即可,采用插件的形式進行封裝 (這里有個問題,高版本的按需導入樣式存在問題,這里的封裝僅僅按需導入插件,樣式使用的總樣式)
(2). 步驟
A. 封裝register-element.ts文件(插件形式)
import { App } from 'vue'; import 'element-plus/dist/index.css'; //全局樣式 import { ElButton, ElCheckbox } from 'element-plus'; const components = [ElButton, ElCheckbox]; export default function (app: App): void { // 注冊全局組件 for (const cItem of components) { app.component(cItem.name, cItem); } }
B. 封裝global文件夾下的index.ts文件,統一出口
import { App } from 'vue'; import registerElement from './register-element'; // 插件的形式對外導出(函數模式) export function golbalRegister(app: App): void { app.use(registerElement); }
C. 在main.ts中進行導入
import { createApp } from 'vue'; import App from './App.vue'; // 按需引入element-plus import { golbalRegister } from './global'; const app = createApp(App); app.use(golbalRegister); // 按需引入element-plus app.mount('#app');
D. 頁面中直接使用即可
<template> <div> <el-button>默認按鈕</el-button> <el-button type="primary">主要按鈕</el-button> <el-button type="success">成功按鈕</el-button> <el-button type="info">信息按鈕</el-button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ setup() { }, }); </script> <style lang="less"></style>
三. axios配置
1. 說明
axios的詳細用法參考之前的文章:https://www.cnblogs.com/yaopengfei/p/12347199.html
這里補充一個通過創建實例的方式進行請求Post表單提交(實際上axios對象也是一個實例)
import axios from 'axios'; const myAxiosInstance = axios.create({ baseURL: 'http://xxxx:8002', timeout: 1000, headers: { 'X-Custom-Header': 'foobar' }, }); const params = new URLSearchParams(); params.append('userAccount', 'admin'); params.append('passWord', '122222'); myAxiosInstance .post('/Api/AdminApi_Areas/SysMainApi/CheckLogin', params) .then((res) => { console.log(res.data); }) .catch((err) => { console.log(err); });
2. 封裝思路
封裝1個類,然后創建一個實例,將實例進行對外導出,里面結合Element-plus的組件,進行請求加載效果的配置
import type { AxiosRequestConfig, AxiosResponse } from 'axios'; /* eslint-disable */ export interface HYRequestInterceptors<T = AxiosResponse> { requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig; requestInterceptorCatch?: (error: any) => any; responseInterceptor?: (res: T) => T; responseInterceptorCatch?: (error: any) => any; } export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig { interceptors?: HYRequestInterceptors<T>; showLoading?: boolean; }

// 以類的方式來封裝axios import axios, { AxiosInstance } from 'axios'; import type { HYRequestInterceptors, HYRequestConfig } from './type'; import { ElLoading, ILoadingInstance } from 'element-plus'; const DEAFULT_LOADING = true; class HYRequest { instance: AxiosInstance; interceptors?: HYRequestInterceptors; showLoading: boolean; loading?: ILoadingInstance; constructor(config: HYRequestConfig) { // 創建axios實例 this.instance = axios.create(config); // 保存基本信息 this.showLoading = config.showLoading ?? DEAFULT_LOADING; this.interceptors = config.interceptors; // 使用攔截器 // 1.從config中取出的攔截器是對應的實例的攔截器 this.instance.interceptors.request.use( this.interceptors?.requestInterceptor, this.interceptors?.requestInterceptorCatch, ); this.instance.interceptors.response.use( this.interceptors?.responseInterceptor, this.interceptors?.responseInterceptorCatch, ); // 2.添加所有的實例都有的攔截器 this.instance.interceptors.request.use( (config) => { if (this.showLoading) { this.loading = ElLoading.service({ lock: true, text: '正在請求數據....', background: 'rgba(0, 0, 0, 0.5)', }); } return config; }, (err) => { return err; }, ); this.instance.interceptors.response.use( (res) => { // 將loading移除 this.loading?.close(); const data = res.data; if (data.returnCode === '-1001') { console.log('請求失敗~, 錯誤信息'); } else { return data; } }, (err) => { // 將loading移除 this.loading?.close(); // 例子: 判斷不同的HttpErrorCode顯示不同的錯誤信息 if (err.response.status === 404) { console.log('404的錯誤~'); } return err; }, ); } request<T>(config: HYRequestConfig<T>): Promise<T> { return new Promise((resolve, reject) => { // 1.單個請求對請求config的處理 if (config.interceptors?.requestInterceptor) { config = config.interceptors.requestInterceptor(config); } // 2.判斷是否需要顯示loading if (config.showLoading === false) { this.showLoading = config.showLoading; } this.instance // eslint-disable-next-line @typescript-eslint/no-explicit-any .request<any, T>(config) .then((res) => { // 1.單個請求對數據的處理 if (config.interceptors?.responseInterceptor) { res = config.interceptors.responseInterceptor(res); } // 2.將showLoading設置true, 這樣不會影響下一個請求 this.showLoading = DEAFULT_LOADING; // 3.將結果resolve返回出去 resolve(res); }) .catch((err) => { // 將showLoading設置true, 這樣不會影響下一個請求 this.showLoading = DEAFULT_LOADING; reject(err); return err; }); }); } get<T>(config: HYRequestConfig<T>): Promise<T> { return this.request<T>({ ...config, method: 'GET' }); } post<T>(config: HYRequestConfig<T>): Promise<T> { return this.request<T>({ ...config, method: 'POST' }); } delete<T>(config: HYRequestConfig<T>): Promise<T> { return this.request<T>({ ...config, method: 'DELETE' }); } patch<T>(config: HYRequestConfig<T>): Promise<T> { return this.request<T>({ ...config, method: 'PATCH' }); } } export default HYRequest;
實例的封裝

// service統一出口 import HYRequest from './request'; import { BASE_URL, TIME_OUT } from './request/config'; const hyRequest = new HYRequest({ baseURL: BASE_URL, timeout: TIME_OUT, // 實例級別的攔截器 interceptors: { requestInterceptor: (config) => { console.log('請求成功的攔截'); return config; }, requestInterceptorCatch: (err) => { console.log('請求失敗的攔截'); return err; }, responseInterceptor: (res) => { console.log('響應成功的攔截'); return res; }, responseInterceptorCatch: (err) => { console.log('響應失敗的攔截'); return err; }, }, }); export default hyRequest;
//測試自己封裝的axios import hyRequest from './index'; // 下面是表單提交到參數封裝 const params = new URLSearchParams(); params.append('userAccount', 'admin'); params.append('passWord', '123456'); // 封裝返回值類型 interface DataType { status: string; msg: string; data: unknown; } hyRequest .post<DataType>({ url: '/Api/AdminApi_Areas/SysMainApi/CheckLogin', data: params, // showLoading: false, // headers: {}, // baseURL: '', }) .then((res) => { console.log(res); console.log(res.status, res.msg, res.data); }) .catch((err) => { console.log(err); });
四. vscode配置
1. 在vscode中設置選項中,輸入配置,然后選擇settings.json,進行配置
2. 分享一個vscode的配置

{ "workbench.iconTheme": "vscode-great-icons", "editor.fontSize": 17, "eslint.migration.2_x": "off", "[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "files.autoSave": "afterDelay", "editor.tabSize": 2, "terminal.integrated.fontSize": 16, "editor.renderWhitespace": "all", "editor.quickSuggestions": { "strings": true }, "debug.console.fontSize": 15, "window.zoomLevel": 1, "emmet.includeLanguages": { "javascript": "javascriptreact" }, "explorer.confirmDragAndDrop": false, "workbench.tree.indent": 16, "javascript.updateImportsOnFileMove.enabled": "always", "editor.wordWrap": "on", "path-intellisense.mappings": { "@": "${workspaceRoot}/src" }, "hediet.vscode-drawio.local-storage": "eyIuZHJhd2lvLWNvbmZpZyI6IntcImxhbmd1YWdlXCI6XCJcIixcImN1c3RvbUZvbnRzXCI6W10sXCJsaWJyYXJpZXNcIjpcImdlbmVyYWw7YmFzaWM7YXJyb3dzMjtmbG93Y2hhcnQ7ZXI7c2l0ZW1hcDt1bWw7YnBtbjt3ZWJpY29uc1wiLFwiY3VzdG9tTGlicmFyaWVzXCI6W1wiTC5zY3JhdGNocGFkXCJdLFwicGx1Z2luc1wiOltdLFwicmVjZW50Q29sb3JzXCI6W1wiRkYwMDAwXCIsXCIwMENDNjZcIixcIm5vbmVcIixcIkNDRTVGRlwiLFwiNTI1MjUyXCIsXCJGRjMzMzNcIixcIjMzMzMzM1wiLFwiMzMwMDAwXCIsXCIwMENDQ0NcIixcIkZGNjZCM1wiLFwiRkZGRkZGMDBcIl0sXCJmb3JtYXRXaWR0aFwiOjI0MCxcImNyZWF0ZVRhcmdldFwiOmZhbHNlLFwicGFnZUZvcm1hdFwiOntcInhcIjowLFwieVwiOjAsXCJ3aWR0aFwiOjExNjksXCJoZWlnaHRcIjoxNjU0fSxcInNlYXJjaFwiOnRydWUsXCJzaG93U3RhcnRTY3JlZW5cIjp0cnVlLFwiZ3JpZENvbG9yXCI6XCIjZDBkMGQwXCIsXCJkYXJrR3JpZENvbG9yXCI6XCIjNmU2ZTZlXCIsXCJhdXRvc2F2ZVwiOnRydWUsXCJyZXNpemVJbWFnZXNcIjpudWxsLFwib3BlbkNvdW50ZXJcIjowLFwidmVyc2lvblwiOjE4LFwidW5pdFwiOjEsXCJpc1J1bGVyT25cIjpmYWxzZSxcInVpXCI6XCJcIn0ifQ==", "hediet.vscode-drawio.theme": "Kennedy", "editor.fontFamily": "Source Code Pro, 'Courier New', monospace", "editor.smoothScrolling": true, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "workbench.colorTheme": "Atom One Dark", "vetur.completion.autoImport": false, "security.workspace.trust.untrustedFiles": "open", "eslint.lintTask.enable": true, "eslint.alwaysShowStatus": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": true } }
五. 區分不同環境
1. 方案1-手動修改
(不可取)
//寫法1:每次手動改 const BASE_URL = 'https://www.ypf.org/test'; const BASE_NAME = 'ypf'; export { BASE_URL, BASE_NAME };
2. 方案2-根據process.env.NODE_ENV進行區分
(推薦)
原理:根據cli內置的一個值, process.env.NODE_ENV ,開發環境下為development,生產環境下為production,測試環境下為test,編寫一個config.ts文件,if判斷,從而對外導出。
分享config.ts代碼
//寫法2:根據process.env.NODE_ENV進行區分 // 開發環境: development // 生成環境: production // 測試環境: test let BASE_URL = ''; if (process.env.NODE_ENV === 'development') { BASE_URL = 'http://127.0.0.1:8000/'; } else if (process.env.NODE_ENV === 'production') { BASE_URL = 'http://ypf.org/prod'; } else { BASE_URL = 'http://ypf.org/test'; } export { BASE_URL };
3. 方案3-編寫不同環境變量配置文件
(推薦)
詳見:https://cli.vuejs.org/zh/guide/mode-and-env.html#模式
(1). 定義3個不同的文件,分別如下,這三個名稱是固定的,分別在里面定義變量。
.env (各種環境都可以獲取)
.env.development (開發環境獲取)
.env.production (生產環境獲取)
.env代碼如下:
/* 開發和生產環境都能獲取 */ VUE_APP_NAME=ypf0
.env.development 代碼如下:
VUE_APP_BASE_URL=https://ypf.org/dev VUE_APP_BASE_NAME=ypf2
.env.production代碼如下:
VUE_APP_BASE_URL=https://ypf.org/prod VUE_APP_BASE_NAME=ypf1
特別注意:只有 NODE_ENV,BASE_URL 和以 VUE_APP_ 開頭的變量將通過 webpack.DefinePlugin 靜態地嵌入到客戶端側的代碼中。
(2). 測試代碼
需要用process.env.xxx進行調用
export default defineComponent({ setup() {// 測試寫法3 console.log('測試寫法3'); console.log(process.env.VUE_APP_BASE_URL); console.log(process.env.VUE_APP_BASE_NAME); console.log(process.env.VUE_APP_NAME); }, });
!
- 作 者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲 明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲 明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。