以前使用過 Vue 開發後臺、中臺項目,也作過移動端 H5,弄過一點小的前端架構。每作一個項目都會收穫了不同的經驗和理解。下面我把這些點點滴滴的經驗總結下來,作一個系列的文章分享和階段性的總結。javascript
常規操做,先點贊後觀看哦!你的點贊是我創做的動力之一!css
我將從 16 個方面來論述 vue 開發過程當中的一些技巧和原理。固然因爲篇幅有限,先論述前 8 個問題,下節將完成全系列內容。html
本篇文章將圍繞下列問題進行論述:前端
實踐以前:我但願你有以下準備,或者知識儲備。vue
- 瞭解
npm/yarn/git/sass/pug/vue/vuex/vue-router/axios/mock/ssr/jest
的使用和原理。- 固然上面知識不瞭解也不要緊哈哈哈,文章中會提到大體用法和做用。
代碼提交記錄是一個很好的代碼修改日誌。規範的代碼提交記錄,無論在平時代碼開發維護過程當中,仍是在定位 bug 或者回退版原本說都是極爲重要。java
兩種作法:node
爲了規範提交,我使用了以下插件:webpack
yarn add -D commitizen conventional-changelog cz-conventional-changelog
複製代碼
安裝依賴時,要注意是不是生產環境須要的。顯然
commitizen
只在開發環境中使用。-D
只在dev
環境使用ios
在 package.json
中添加配置git
{
//...
"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 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 './reset.scss';
import './varibles.scss';
improt './utils/scss';
複製代碼
在 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-body{
.cardbox-card-item {
.cardbox-card-item-title {
// ...
}
}
}
}
}
}
複製代碼
block-name__element-name--color
card__item
使用 __
鏈接card__item--warning
使用 --
咱們使用 bem 改造樣式
.cardbox {
.card {
.&__item {
&__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'))
}
}
複製代碼
iconfont.eot
iconfont.ttf
iconfont.woff
iconfont.woff2
icon
組件化<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 步來寫好一個公共組件
components
目錄來存放基礎組件app-xxx
或 appXxx
,新建一個 app-button
目錄,新建 index.vue
編寫組件以前首先要設計組件,根據組件的不變性和可變性原則編寫。不變性是組件的核心,可變性根據參數對組件對相關部分進行調節,實現可選擇的功能。
<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
,即便暫時不寫單元測試,也要寫好一個 demo
,使之能正常的運行添加 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 = {
dev: 'http://xxxx:8080',
mock: 'http://xxxx',
feature: 'http://xxxx',
test: 'http://xxxx',
prod: 'http://xxxx'
}
export const baseURL = () => {
if (process.env.NODE_ENV === 'production') {
return api.prod
} else if (process.env.NODE_ENV === 'testing') {
return api.test
} else if (process.env.NODE_ENV === 'mock') {
return api.mock
} else if (process.env.NODE_ENV === 'feature') {
return api.feature
} else {
return api.dev
}
}
複製代碼
utils
工具咱們如今將 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)
複製代碼
若是須要處理數據,要麼使用一箇中間工具處理,要麼在頁面裏面處理。固然仍是實際問題實際分析。
mock
模擬數據通常就是兩種方案,一是模擬後端,使用遠程在線 JSON 服務器。另一種搭建本地 JSON 或者 使用現成的 Node 服務器攔截請求。
這兩種方式各有千秋,沒有優劣之分,適合就是最好的。
mock
我用過的遠程在線mock
api
,免費版只支持 2 我的共同編輯api
管理太凌亂,api
,須要本身搭建使用遠程mock
的優勢:
mock
mock
,與接口文檔放在一塊兒查看更加方便。缺點:須要本身另外搭建服務器,只支持靜態的mock
,不能與單元測試結合使用
webpack
內部 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)
}
}
複製代碼
json-server
搭建 主要分爲下面幾步npm
安裝 json-server
npm
腳本命令,引入 mock
配置文件mock
路由匹配規則比較簡單這裏不詳細描述了!
本地的缺點在於須要
api
文檔寫mock
數據格式mock
那麼完善,支持restful
須要去研究下mock
工具優勢在於
api
文檔mock
數據JavaScipt
動態處mock
,能夠與單元測試結合使用本篇文章耗費做者一個多星期的業餘時間,存手工敲打 6000+字,同時收集,整理以前不少技巧和邊寫做邊思考和總結。若是能對你有幫助,即是它最大的價值。都看到這裏還不點贊,太過不去啦!😄
因爲技術水平有限,文章中若有錯誤地方,請在評論區指出,感謝!
文中大多數代碼將在suo-design-pro 中更新
項目有時間會盡可能完善
寫實踐總結性文章真的很耗費時間。如何文章中有幫到你的地方分享下唄,讓更多人看到!
上述功能配置,均將在 suo-design-pro 中實現,但願能持續關注!