嘍哈嘍 大家好,今天給大家分享一下 創建Vue 工程的小工具 vuecli
Vue cli 就是 vue的 client,客戶端,是一個命令行工具,能幫我們快速構建一個 vue的標準工程。是官方cli,支持vue2和vue3不同版本。初始化一個vue工程,引入相關依賴。
首先你本地需要有node環境,包括node和npm。請參考官方文檔安裝node環境。 https://nodejs.org/en/
你可以在命令行狀態下敲入 如下命令檢查自己是否有node環境
有了node環境,我們可以通過npm來安裝vuecli,當然,如果你習慣用yarn,請先使用 npm安裝yarn。
檢查vuecli是否安裝成功
cli安裝好后,我們可以創建標準的vue工程了。
命令行敲入 vue create XXX
其中XXX是你希望的工程名,會在當前目錄下生成同名文件夾的工程文件。
提示要創建Vue的哪個版本,我們選擇第一項直接回車,就是創建Vue2的默認工程。
經過一系列提示后,工程就創建好了,我的工程名是home,最后提示我進入home后,運行 yarn serve 或者 npm run serve ,來啟動默認的webpack dev server來運行服務。
服務啟動完成, 提示我可以訪問 localhost:8080 來訪問我默認創建的這個vue 前端頁面
我們打開瀏覽器,在地址欄鍵入 http://localhost:8080 后回車
一切順利的話我們會看到如下頁面
這個就是我們通過vuecli默認創建出來的一個vue工程了的默認頁面。
工程目錄結構如下。
node_modules: 前端工程的依賴庫,node-js的npm會通過package.json 管理 本地包,其中外部依賴庫,會在npm install時,安裝到node-modules下。
public: 需要靜態發布的資源目錄,默認里面放了一個index.html,這個就是我們開發頁面的基礎html。之后vue創建的動態dom都是掛在到這個頁面上的,如果存在不在npm下管理的第三方插件,可以通過 public這個文件來發布,并在index.html中載入這些外部依賴。
src:源代碼目錄,其中main.js 就是我們前端程序的主入口。根組件就是從這里最開始實例化的,這個根組件通常就是 App.vue。通常會在App.vue中搭建 站點的主結構,引入vue router,在App.vue下根據url映射決定顯示哪個視圖組件。
.gitignore: git倉庫的忽略文件,當前目錄下哪些文件不需要git倉庫托管,可以在ignore文件中記下文件名,在git add時會忽略掉那些文件。
babel.config.js: 因為我們的瀏覽器不一定會認識現在主流的es6語法,所以我們編寫的js代碼,是通過webpack編譯發布的,其中babel就是用來解析es6的,es6也存在不同的版本,可以通過這個文件,配置es6的特性。
package.json : npm的包描述文件,當前工程的特性在這個文件中
README.md:本身是個markdown格式的文件,markdown是類似html的格式化文檔,通過特殊字符表達特定格式,一般網站都會默認讀取README.md形成說明頁面。
除了默認的依賴,我通常會在package.json中添加如下一下,以方便開發。
其中pug可以以pug語言來書寫html模板,大大減少了不必要的字符,少敲了很多代碼。
sass是在寫css時,語法和pug高度匹配,非常節省代碼
這里需要注意的是,node-sass對node-js版本是有對應關系的,如果版本不匹配,工程會有編譯錯誤,請在node-sass的官方網站檢索對應的node-js的版本,下載對應的node-sass。
相應的,sass-loader與node-sass也是有版本對應關系的,要注意
言
之前使用過 Vue 開發后臺、中臺項目,也做過移動端 H5,弄過一點小的前端架構。每做一個項目都會收獲了不一樣的經驗和理解。下面我把這些點點滴滴的經驗總結下來,做一個系列的文章分享和階段性的總結。
常規操作,先點贊后觀看哦!你的點贊是我創作的動力之一!
我將從 16 個方面來論述 vue 開發過程中的一些技巧和原理。當然由于篇幅有限,先論述前 8 個問題,下節將完成全系列內容。
本篇文章將圍繞下列問題進行論述:
實踐之前:我希望你有如下準備,或者知識儲備。
了解 npm/yarn/git/sass/pug/vue/vuex/vue-router/axios/mock/ssr/jest 的使用和原理。
當然上面知識不了解也沒關系哈哈哈,文章中會提到大致用法和作用。
代碼提交記錄是一個很好的代碼修改日志。規范的代碼提交記錄,不管在平時代碼開發維護過程中,還是在定位 bug 或者回退版本來說都是極為重要。
兩種做法:
為了規范提交,我使用了如下插件:
yarn add -D commitizen conventional-changelog cz-conventional-changelog
復制代碼
安裝依賴時,要注意是否是生產環境需要的。顯然 commitizen 只在開發環境中使用。-D 只在 dev 環境使用
在 package.json 中添加配置
{
//...
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
復制代碼
在命令行中輸入
git add -A
git-cz
復制代碼
出現了交互輸入方式,規范你的 commit 輸入格式
npm i -g conventional-changelog-cli
復制代碼
增加一個npm 命令,快速生成日志
"genlog": "conventional-changelog -p angular -i .github/CHANGELOG.md -s"
復制代碼
使用yarn命令生成日志
yarn genlog
復制代碼
自動生成的log
# 0.1.0 (2019-12-27)
### Features
* **git:** 增加commitizen工具規范提交 ([58e3937](https://github.com/suoyuesmile/suo-design-pro/commit/58e39370aa838fd99312f73b37d092ffadc85990))
復制代碼
較統一的代碼風格利于閱讀,也利于協作。
使用 eslint 約束基本風格和語法,使用 prettier 自動格式化你的代碼。
{
"eslint": "^5.16.0",
"eslint-config-standard": "^6.2.1",
"eslint-friendly-formatter": "^2.0.7",
"eslint-loader": "^2.1.2",
"eslint-plugin-html": "^2.0.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^2.3.1",
"eslint-plugin-vue": "^5.0.0"
}
復制代碼
使用兩個插件,一個 plugin:vue/essential,一個是 standard。 vue/essential 為了在 vue 里面也可以生效。另一個是 standard。 standard 標準文檔
使用 recommend 也可以,采用推薦 lint,更加輕量化
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/essential', 'standard'],
rules: {
quotes: ['error', 'single'],
indent: ['error', 2, { MemberExpression: 'off' }],
'arrow-parens': 0,
'no-loop-func': 2,
'space-before-function-paren': ['error', 'never'],
indent: ['error', 2, { SwitchCase: 1 }]
},
parserOptions: {
parser: require.resolve('babel-eslint'),
ecmaVersion: 2018,
sourceType: 'module'
}
}
復制代碼
rules 的規則 { 規則名:[是否關閉/規則等級,配置的值,只對部分配置] } indent: ['error', 2, { SwitchCase: 1 }] 兼容 prettier,prettier 會將代碼格式化成 eslint 報錯的情況。 規則等級:0 關閉 1 警告 2 報錯
{
"printWidth": 150,
"singleQuote": true,
"trailingComma": "none",
"semi": false,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"proseWrap": "preserve",
"overrides": [
{
"files": ["*.json", ".eslintrc", ".tslintrc", ".prettierrc", ".tern-project"],
"options": {
"parser": "json",
"tabWidth": 2
}
},
{
"files": "*.{css,sass,scss,less}",
"options": {
"parser": "css",
"tabWidth": 2
}
},
{
"files": "*.ts",
"options": {
"parser": "typescript"
}
},
{
"files": "*.vue",
"options": {
"parser": "vue"
}
},
{
"files": "*.md",
"options": {
"parser": "markdown"
}
}
]
}
復制代碼
{
// prettier
"prettier.singleQuote": true,
"prettier.semi": false,
"prettier.tabWidth": 2,
"[javascript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
復制代碼
我主要從 3 個方面來做一些編碼效率上的改進
vue-cli3+、vue-cli4+ 相比于 vue-cli2+ 最大的改變就是將約定俗稱的配置,全部公共化了,也就是做了一次二次封裝。這樣的好處在于,我們不必要在繁多的配置代碼中尋找需要的配置。
簡單新建一個配置入口就能操作我們大多數想要的功能。在 root 目錄下新建一個 vue.config.js 文件,作為我們 webpack 的配置文件。
初始化 vue 配置
const autoprefixer = require('autoprefixer')
module.exports = {
publicPath: process.env === 'production' ? '' : '/',
outputDir: 'dist',
assetsDir: 'static',
filenameHashing: true,
lintOnSave: true,
runtimeCompiler: false,
transpileDependencies: [/\/node_modules\/vue-echarts\//, /\/node_modules\/resize-detector\//],
productionSourceMap: false
}
復制代碼
簡單的配置完成后,我們引入一個 sass 工具用于編寫 sass文件
用法見 sass 參考資料!
yarn add -D sass sass-loader
復制代碼
在 assets 目錄中建立一個 styles 文件專門來存放樣式文件,新增入口index.scss文件,便于 JavaScript 引入,增加 utils.scss、reset.scss、varibles 文件。
這些樣式工具都是為了提升我們 scss 開發效率,具有暢快的開發體驗!
為了提升我們代碼的可讀性,復用性。使用 sass 變量必不可少。
還有一點就是利于全局修改樣式,如果需要更換皮膚這個功能,我們只需要更改全局的主題色,即可更換主題,那樣更加方便。
// 主題色
$color-red: #ff3333;
$color-purple: #ff33a9;
$color-orange: #ff8833;
$color-blue: #3377ff;
// 文字色
$color-black: #000;
$color-dark: #333;
$color-deep: #555;
$color-pl: #999999;
$color-weak: #B3B3B3;
$color-white: #fff;
// 背景色
$bg-bar: #F9F9F9;
$bg-page: #F3F3F3;
$bg-page-light: #F9F9F9;
復制代碼
使用變量之后,sass 文件不會直接生效,至少在 vue 文件 里面是訪問不到的。 需要在 vue.config.js 里面增加如下配置。
module.exports = {
// ...
css: {
sourceMap: true,
loaderOptions: {
sass: {
prependData: `
@import "@/assets/styles/variable.scss";
`
}
}
}
}
復制代碼
常規操作, 引入 reset.scss 將默認樣式覆蓋掉
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
html, body {
width: 100%;
height: 100%;
overflow: auto;
margin: 0;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
}
復制代碼
有時候我們發現,光是引入變量還不夠,變量工具只能允許我們在 css 類文件中使用。假如我想著模版中直接使用樣式,有沒有更快的方案呢?
當然有的,我們可以自定義一個常用的樣式工具集。設置一些背景顏色、字體顏色、盒子模型中的常規操作。
要是有設計規范更好哦,我也是常常向設計師提出要求,一定要制定出一套產品的設計規范。
// utils 工具
// 顏色
.bg-red {background-color: $color-red!important;}
.bg-purple {background-color: $color-purple!important;}
.bg-orange {background-color: $color-orange!important;}
.bg-blue {background-color: $color-blue!important;}
.color-red {color: $color-red!important;}
.color-purple {color: $color-purple!important;}
.color-orange {color: $color-orange!important;}
.color-blue {color: $color-blue!important;}
.text-black {color: #000;}
.text-dark {color: #333;}
.text-deep {color: #555;}
.text-weak {color: #B3B3B3;}
.text-white {color: #fff;}
// 字體
.f10 {font-size: 10px;}
.f12 {font-size: 12px;}
.f14 {font-size: 14px;}
.f15 {font-size: 15px;}
.f17 {font-size: 17px;}
.f20 {font-size: 20px;}
.f24 {font-size: 24px;}
// 文字對齊
.tl {text-align: left;}
.tc {text-align: center;}
.tr {text-align: right;}
// 浮動與清除浮動
.fl {float: left;}
.fr {float: right;}
.fix {*zoom: 1;}
.fix:after{display:table; content:''; clear:both;}
// 顯示
.dn{display:none;}
.di{display:inline;}
.db{display:block;}
.dib{display:inline-block;}
.dt{display:table;}
div.dib{*display:inline; *zoom:1;}
.vm {vertical-align: middle;}
.vib {display:inline-block; vertical-align: middle;}
// 定位
.pr {position: relative;}
.pa {position: absolute;}
.pf {position: fixed;}
// 盒子模型
.ml4 {margin-left: 4px;}
.mr4 {margin-right: 4px;}
.mt4 {margin-top: 4px;}
.mb4 {margin-bottom: 4px;}
.ml8 {margin-left: 8px;}
.mr8 {margin-right: 8px;}
.mt8 {margin-top: 8px;}
.mb8 {margin-bottom: 8px;}
.ml12 {margin-left: 12px;}
.mr12 {margin-right: 12px;}
.mt12 {margin-top: 12px;}
.mb12 {margin-bottom: 12px;}
.ml16 {margin-left: 16px;}
.mr16 {margin-right: 16px;}
.mt16 {margin-top: 16px;}
.mb16 {margin-bottom: 16px;}
.ml20 {margin-left: 20px;}
.mr20 {margin-right: 20px;}
.mt20 {margin-top: 20px;}
.mb20 {margin-bottom: 20px;}
.ml24 {margin-left: 24px;}
.mr24 {margin-right: 24px;}
.mt24 {margin-top: 24px;}
.mb24 {margin-bottom: 24px;}
.ml10 {margin-left: 10px;}
.mr10 {margin-right: 10px;}
.mt10 {margin-top: 10px;}
.mb10 {margin-bottom: 10px;}
.ml15 {margin-left: 15px;}
.mr15 {margin-right: 15px;}
.mt15 {margin-top: 15px;}
.mb15 {margin-bottom: 15px;}
// 按鈕禁用
.disabled{outline:0 none; cursor:default!important; opacity:.4; filter:alpha(opacity=40); -ms-pointer-events:none; pointer-events:none;}
復制代碼
最后一步,新建一個入口文件,將樣式工具類全部導入進來,供主程序引入。
// index.scss 文件
// @import './varibles.scss'
@import './reset.scss';
@import './utils.scss';
復制代碼
varibles.scss vue 配置中引入,這里無需引入
在 main.js 中直接引入 index.scss
import '@/assets/styles/index.scss'
復制代碼
在頁面中寫 css/scss 加上 scoped,scoped 的功能就是使頁面的樣式是局部的,不讓影響其他頁面的樣式。
我們大多數人時候會遇到問題,樣式嵌套太多了怎么命名
BEM是塊(block)、元素(element)、修飾符(modifier)的簡寫,由 Yandex 團隊提出的一種前端 CSS 命名方法論。
名字太長易讀性太差
.cardbox {
.cardbox-card {
.cardbox-card-wrapper
.cardbox-card-wrapper-header {
.cardbox-card-wrapper-header-title {
// ...
}
}
.cardbox-card-wrapper-body{
.cardbox-card-item {
.cardbox-card-item-title {
// ...
}
}
}
}
}
}
復制代碼
block-name__element-name--color
我們使用 bem 改造樣式
.cardbox {
&__header {
&__title {
//...
}
}
&__body {
&__item {
&__title {
//...
}
}
}
}
復制代碼
bem 一般推薦子元素嵌套盡量在2-3層以內
但是我們發現樣式子元素嵌套有點多,使用了兩重子元素嵌套。
大致原理是嘗試分離父子元素的關系,把卡片本身當作一個塊看待。
下面來試著去減少嵌套:
.cardbox {
&__header {
&__title {
//...
}
}
&__body {
.card {
&__title {
//...
}
}
}
}
復制代碼
現在編寫樣式效率提高也更加規范了,那么編寫 HTML 也是有很多累贅的代碼。
比如大多數標簽都是前開后閉的。通過 pug 我們可以省略很多字符的敲打,下面我們談談如何使用 pug 編寫模版。
當然喜歡哪種 HTML 編寫風格見人見智啦,我自己更加傾向 pug,那種縮進和簡潔的表達,有種在寫 scss 的感覺。
yarn add -D pug pug-html-loader pug-plain-loader
復制代碼
module.exports = {
// ...
chainWebpack: (config) => {
config.module
.rule('pug')
.test(/\.pug$/)
.use('pug-html-loader')
.loader('pug-html-loader')
.end()
}
}
復制代碼
使用 scss 工具與 pug 完美搭配,少寫很多代碼
// 登陸
<template lang="pug">
.login
h1.login__title.ml15 注冊/登陸
.login__form.mt15.ml15
van-field.login__form__input(placeholder="輸入手機號" v-model="phone")
.login__form__protocol.mt15
.login__form__protocol__tips.dib.text-weak 注冊或登錄即表示同意
.login__form__protocol__name.dib.color-orange 《用戶協議》
app-button.mt15(size="large"
theme="orange"
:disabled="phone.length !== 11"
@click="handleSubmit"
) 下一步
</template>
復制代碼
我們已經引入了樣式,接下來我將談談其他資源的引入
我暫時把資源分為下面幾種
增加 vue.config.js 配置 ,設置assets別名
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
//...
chainWebpack: (config) => {
config.resolve.alias.set('@', resolve('src')).set('@assets', resolve('src/assets'))
}
}
復制代碼
<template>
<i class="iconfont" v-on="$listeners" :class="name"></i>
</template>
<script>export default {
props: {
name: String
}
}</script>
<style lang="scss" scoped>.iconfont {
font-size: 16px;
color: $color-icon;
}</style>
復制代碼
讓圖片組件化,我們再來寫一個 img 組件
<template lang="pug">
img(
:src="require(`@/assets/images/${name}.png`)"
v-bind="$attrs"
v-on="$listeners"
:style="{'width': width ? width + 'px' : size + 'px', 'height': height ? height + 'px' : size + 'px' }")
</template>
<script>
export default {
name: 'app-img',
props: {
name: {
type: String,
default: ''
},
size: {
type: Number,
default: 16
},
width: {
type: Number,
default: 0
},
height: {
type: Number,
default: 0
}
}
}
</script>
復制代碼
使用 vue-router,使用import() 生成異步路由,只有在訪問時候才會加載模塊。
為什么使用 import() 會異步加載模塊?
MDN:在您希望按照一定的條件或者按需加載模塊的時候,動態import() 是非常有用的。而靜態型的 import 是初始化加載依賴項的最優選擇,使用靜態 import 更容易從代碼靜態分析工具和 tree shaking 中受益。
說白了就是起到一個按需加載的目的。現在大多數實現的按需加載,基本都是依賴 import() 這個方法。
yarn add vue-router
復制代碼
安裝完 router,在編寫 router 先創建頁面
src 目錄下新增 views 目錄存放頁面文件。創建 index 目錄和 home 頁面
<template lang="pug">
.home 首頁
</template>
<script>export default {
}</script>
<style lang="scss" scoped>
</style>
復制代碼
const routes = [
{
// 首頁
path: '/',
name: 'index',
redirect: '/home',
component: App,
children: [
{
// 首頁
path: 'home',
name: 'home',
// 路由懶加載
component: () =>
import(
/* webpackChunkName: "index" */ '../views/index/home.vue'
)
}
]
}
]
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',
routes: routes,
base: process.env.BASE_URL,
props: true
})
export default router
復制代碼
在 vue.config.js 中增加配置,開發環境可以訪問到,恢復正常
module.exports = {
// ...
devServer: {
historyApiFallback: true
}
}
復制代碼
關于路由還有很多可以研究到地方,可以自行研究哦!
一般來說,我們根據組件的復用度,分給基礎(公共)組件和業務組件。
為了節省時間,快速開發,這里基礎組件大部分引用開源組件。當然不能直接就用哦。
一般要進行二次封裝,也就是高階組件開發。
下面我們先引入 vant 組件
yarn add vant
復制代碼
下面 7 步來寫好一個公共組件
編寫組件之前首先要設計組件,根據組件的不變性和可變性原則編寫。不變性是組件的核心,可變性根據參數對組件對相關部分進行調節,實現可選擇的功能。
<template lang="pug">
div.dib
van-button.btn(
@click="$emit('click')"
:class="getClass" v-bind="$attrs"
:style="{'width': size === 'large' ? '345px': '', 'backgroundColor': getBgColor, borderColor: getBgColor, color: getBgColor}")
slot
</template>
<script>import { Button } from 'vant'
import Vue from 'vue'
import { getColor } from '@/utils'
Vue.use(Button)
export default {
name: 'app-button',
props: {
type: {
type: String,
default: 'primary'
},
theme: {
type: String,
default: 'blue'
},
size: {
type: String,
default: ''
}
},
computed: {
getClass() {
if (!this.type) {
return ''
}
return `app-btn--${this.type}`
},
getBgColor() {
if (!this.theme) {
return ''
}
return getColor(this.theme)
}
}
}</script>
<style lang="scss" scoped>
.app-btn {
::v-deep &--primary {
padding: 8px 30px;
height: 40px;
border-radius: 4px;
font-size: 15px;
font-weight: 400;
line-height: 19px;
color: white!important;
}
::v-deep &--minor {
padding: 5px 10px;
height: 26px;
border-radius: 14px;
font-size: 12px;
font-weight: 400;
line-height: 16px;
background-color: #fff!important;
}
::v-deep &--rect {
padding: 5px px;
height: 49px;
font-size: 14px;
color: white!important;
}
}
</style>
復制代碼
::v-deep 樣式深覆蓋,scoped 情況下覆蓋組件樣式,不改變其樣式
一句話言:只要可能被其他人用的公共方法和組件,注釋或文檔是很重要的,對自己的代碼負責哈。
其他用法參照 vant
新建一個文件 global 存放全局組件注冊,在 main.js 引入
import Vue from 'vue'
import appButton from '@/components/app-button'
Vue.component('app-button', appButton)
復制代碼
添加 demo 頁面和路由
<template lang="pug">
div(class="base")
// 按鈕組件
app-button.mt4(theme="blue") 確認支付
app-button(theme="orange") 確認支付
app-button(theme="purple") 確認支付
app-button.mt4(theme="red") 確認支付
app-button(theme="grey") 確認支付
app-button.mt4(theme="blue" size="large") 修改地址
app-button.mt4(theme="orange" size="large") 修改地址
app-button.mt4(theme="purple" size="large") 修改地址
app-button.mt4(theme="red" size="large") 修改地址
app-button.mt4(theme="grey" size="large") 修改地址
app-button.mt4(theme="blue" type="minor") 確認收貨
app-button(theme="orange" type="minor") 確認收貨
app-button(theme="purple" type="minor") 確認收貨
app-button(theme="red" type="minor") 修改地址
app-button(theme="grey" type="minor") 修改地址
app-button.mt4(theme="blue" type="rect") 確認收貨
app-button(theme="orange" type="rect") 確認收貨
app-button(theme="purple" type="rect") 確認收貨
app-button(theme="red" type="rect") 修改地址
app-button(theme="grey" type="rect") 修改地址
</template>
<script>export default {
}</script>
<style lang="scss">
</style>
復制代碼
基本上就是對 axios 的封裝,封裝主要有兩個目的。
網上已經有很多類似的文章了, 我這里給出我常用的封裝方案。
// .env-default.js 文件
// 不同環境訪問不同的路徑
const api = {
develop: 'http://xxxx:8080',
mock: 'http://xxxx',
feature: 'http://xxxx',
test: 'http://xxxx',
production: 'http://xxxx'
}
export const baseURL = api[process.env.NODE_ENV || 'dev']
復制代碼
因為每個人開發環境,mock環境不一定相同,這個文件建議 gitignore忽略掉。模版可以寫在 readme 文檔中,啟動項目時加入文件。
我們現在將 axios 封裝成我們自己需要的配置,然后定義四個常用的請求方法供調用
// utils/http.js 文件
import axios from 'axios'
import { baseURL } from '../../.env-defalut.js'
// axios 配置
const defaultBaseUrl = 'http://localhost:8080/'
// 默認超時時間
axios.defaults.timeout = 15000
// 數據接口域名統一配置.env
axios.defaults.baseURL = baseURL || defaultBaseUrl
// http request 攔截器
axios.interceptors.request.use(
(config) => {
config.headers = {
}
return config
},
(err) => {
return Promise.reject(err)
}
)
// http response 攔截器
axios.interceptors.response.use(
(response) => {
return response
},
(error) => {
const data = error.response.data
return Promise.reject(data || error)
}
)
export default axios
/**
* fetch 請求方法
* @param {*} url
* @param {*} params
*/
export function fetch(url, params = {}) {
return new Promise((resolve, reject) => {
axios
.get(url, {
params: params
})
.then((response) => {
resolve(response.data)
})
.catch((err) => {
reject(err)
})
})
}
/**
* post 請求方法,發送數據格式 json
* @param {*} url
* @param {*} data
*/
export function post( url,
data = {},
config = {
transformRequest: [
function(fData, headers) {
headers['Content-Type'] = 'application/json'
return JSON.stringify(fData)
}
]
}
) {
return new Promise((resolve, reject) => {
axios.post(url, data, config).then(
(response) => {
resolve(response.data)
},
(err) => {
reject(err)
}
)
})
}
/**
* patch 請求方法,發送數據格式 json
* @param {*} url
* @param {*} data
*/
export function patch(url, data = {}) {
return new Promise((resolve, reject) => {
axios
.patch(url, data, {
transformRequest: [
function(fData, headers) {
headers['Content-Type'] = 'application/json'
return JSON.stringify(fData)
}
]
})
.then(
(response) => {
resolve(response.data)
},
(err) => {
reject(err)
}
)
})
}
export function del(url, data) {
return new Promise((resolve, reject) => {
axios.delete(url, { data }).then(
(response) => {
resolve(response.data)
},
(err) => {
reject(err)
}
)
})
}
復制代碼
首先要制定一個 api 的原則 我的原則一般是這些:
好處在于:不在 api 里面處理數據,api里面的接口和接口文檔上一樣。避免別人引用我的api,還要去看代碼,只需要看文檔就好了。
例子:想象這樣一種情況,別人引用了我的 api,突然發現響應數據不對。首先它排查到頁面數據沒更改。看了api文檔,數據也沒問題,最后發現我在寫 api 的時候進行了處理,這個 api 呢又不能改動,改了影響我自己的模塊。只能它在重新寫一個api,這樣顯得很繁雜了,不夠干凈優雅。
import { fetch, post } from '@/utils/http'
// 用戶登陸
export const login = data => post('/user/login', data)
// 獲取用戶信息
export const getUserInfo = (data) => fetch('/api/user/info', data)
復制代碼
如果需要處理數據,要么使用一個中間工具處理,要么在頁面里面處理。當然還是實際問題實際分析。
一般就是兩種方案,一是模擬后端,使用遠程在線 JSON 服務器。另外一種搭建本地 JSON 或者 使用現成的 Node 服務器攔截請求。
這兩種方式各有千秋,沒有優劣之分,適合就是最好的。
我用過的遠程在線mock
使用遠程mock的優點:
缺點:需要自己另外搭建服務器,只支持靜態的mock,不能與單元測試結合使用
devServer: {
// 接口未實現情況下,使用mock
before: require('./mock')
}
復制代碼
基本原理:主要是使用 node 讀取文件,轉換成 JSON 格式,使用mock.js 模擬數據,最后 webpack 攔截請求生成json響應數據
const Mock = require('mockjs')
module.exports = (app) => {
function getJsonFile (filePath) {
var json = fs.readFileSync(path.resolve(__dirname, filePath), 'utf-8')
return JSON.parse(json)
},
const returnMock = (datafile, res, req) => {
setTimeout(() => {
var json
if (/\.json$/.test(datafile)) {
// json文件暴露的是mock的模板
json = getJsonFile(datafile)
} else if (/\.js$/.test(datafile)) {
json = require(datafile)(req.query)
}
res.json(Mock.mock(json))
}, 500)
}
}
復制代碼
比較簡單這里不詳細描述了!
本地的缺點在于需要
優點在于
本篇文章耗費作者一個多星期的業余時間,存手工敲打 6000+字,同時收集,整理之前很多技巧和邊寫作邊思考和總結。如果能對你有幫助,便是它最大的價值。都看到這里還不點贊,太過不去啦!
由于技術水平有限,文章中如有錯誤地方,請在評論區指出,感謝!
文中大多數代碼將在suo-design-pro 中更新
項目有時間會盡量完善
寫實踐總結性文章真的很耗費時間。如何文章中有幫到你的地方分享下唄,讓更多人看到!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。