preface
I used Vue to develop background and mid-stage projects, as well as mobile TERMINAL H5 and a small front-end architecture. I gained different experience and understanding from each project. Below, I sum up the experience of these dribs and drabs to make a series of articles to share and periodic summary.
General operation, first click “like” after watching oh! Your praise is one of the motivations for my creation!
An overview of
The problem
I will discuss some of the techniques and principles of vUE development from 16 aspects. Of course, due to the limited space, the first 8 questions will be discussed first, and the next section will complete the whole series.
This article will focus on the following issues:
- How to standardize your Git commit and automatically generate and commit logs?
- How can you configure and use Sass and PUG to improve your coding efficiency?
- How to deal with your code style issues, and how to use PertTier and ESLint to solve the efficient style dilemma?
- How to manage page routing, how to write asynchronous routing?
- How do you write components and import component libraries?
- How do you manage your resources, how do you introduce ICONS, styles?
- How to encapsulate your AXIos and manage your API?
- How can YOU mock your data to achieve real separation of front and back ends?
practice
Before you practice: I hope you have the following preparation, or knowledge.
- To understand
npm/yarn/git/sass/pug/vue/vuex/vue-router/axios/mock/ssr/jest
The use and principle of.- Of course, the above knowledge does not matter ha ha ha, the article will mention the general usage and role.
How to regulate Git commit
The code commit log is a good code change log. Regular code submission records are extremely important in the maintenance and development of code, as well as in locating bugs or rolling back versions.
The principle of
Two ways:
- Standardize git’s commit principles manually or as a team. This depends on self-awareness, good habits after the formation of no problem
- Use plug-in specifications, such as the one below
To standardize submission, I use the following plug-ins:
- commitizen
- conventional-changelog
- cz-conventional-changelog
- conventional-changelog-cli
The solution
Install a series of plug-in dependencies
yarn add -D commitizen conventional-changelog cz-conventional-changelog
Copy the code
When installing dependencies, be careful if they are required by the production environment. Apparently commitizen is only used in development environments. -d is used only in the Dev environment
Configuring dependent Paths
Add configuration in package.json
{
/ /...
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
Copy the code
Enter it on the command line
git add -A
git-cz
Copy the code
There are interactive input methods, standardize yourcommit
Input format
Generate the CHANGELOG
npm i -g conventional-changelog-cli
Copy the code
Added a NPM command to quickly generate logs
"genlog": "conventional-changelog -p angular -i .github/CHANGELOG.md -s"
Copy the code
Run the yarn command to generate logs
yarn genlog
Copy the code
Automatically generated logs
# 0.1.0 from (2019-12-27)
### Features
* **git:**Added commitizen tool specification submission ([58e3937] (https://github.com/suoyuesmile/suo-design-pro/commit/58e39370aa838fd99312f73b37d092ffadc85990))
Copy the code
How do you manage code style
A more uniform code style facilitates reading and collaboration.
Principles and solutions
Use esLint to constrain basic style and syntax, while prettier automatically formats your code.
practice
Install esLint dependencies
{
"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"
}
Copy the code
Use two plugins, one plugin:vue/essential and one is Standard. Vue /essential to work in vue as well. The other is Standard. Standard Standard documents
You can also use Recommend, use Lint, and be more lightweight
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'
}
}
Copy the code
Rules rules that can be customized
Rules {Rule name: [Disable/rule level, configured value, only partially configured]} indent: [‘error’, 2, {SwitchCase: 1}] compatible with Prettier, where prettier formats code into an esLint error. Rule level: 0 Disable 1 Warning 2 Error
Using a prettier
Example Configure the prettier file
{
"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"
}
}
]
}
Copy the code
Enable vscode automatic formatting
{
// prettier
"prettier.singleQuote": true,
"prettier.semi": false,
"prettier.tabWidth": 2,
"[javascript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Copy the code
How to improve coding efficiency
Principles and solutions
I will improve the coding efficiency mainly from three aspects
- Upgrade your VUE-CLI to reduce the cost of webpack configuration
- Use SASS to reuse CSS files using functions, mixins, and variables
- Use PUG to reduce the amount of HTML code
practice
Vue-cli3 +, VUe-CLI4 + compared with vue-CLI2 +, the biggest change is that the convention commonly known as the configuration, all the public, that is, to do a secondary encapsulation. The advantage of this is that we don’t have to search through a lot of configuration code to find the configuration we need.
Most of the functions we want can be handled by simply creating a new configuration entry. Create a vue.config.js file in the root directory as our webpack configuration file.
Initialize the VUE configuration
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
}
Copy the code
After the simple configuration, we introduce a sASS tool for writing SASS files
See sASS Resources for usage!
Using Sass
Installation and use
yarn add -D sass sass-loader
Copy the code
How to deal with styles
Create a styles file in assets for style files, add an entry index. SCSS file for JavaScript import, add utils. SCSS, reset. SCSS, varibles files.
These style tools are designed to improve our SCSS development efficiency and have a smooth development experience!
Use varibles variable files
To improve the readability and reusability of our code. Using the sass variable is essential.
Another point is to facilitate the global modification style, if you need to change the skin function, we just need to change the global theme color, you can change the theme, that is more convenient.
/ / theme color
$color-red: #ff3333;
$color-purple: #ff33a9;
$color-orange: #ff8833;
$color-blue: #3377ff;
/ / text color
$color-black: #000;
$color-dark: #333;
$color-deep: #555;
$color-pl: #999999;
$color-weak: #B3B3B3;
$color-white: #fff;
/ / the background color
$bg-bar: #F9F9F9;
$bg-page: #F3F3F3;
$bg-page-light: #F9F9F9;
Copy the code
After using variables, sass files do not take effect directly, at least not in vue files. You need to add the following configuration in vue.config.js.
module.exports = {
// ...
css: {
sourceMap: true.
loaderOptions: {
sass: {
prependData: `
@import "@/assets/styles/variable.scss";
`
}
}
}
}
Copy the code
Override default styles
As a general operation, reset.scss is introduced to override the default styles
/* 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;
}
Copy the code
Use the style toolset
Sometimes we find that introducing variables is not enough, and the variable tools only allow us to use them in CSS class files. If I want to use styles directly in a template, is there a faster solution?
Sure, we can customize a set of common style tools. Set some background colors, font colors, and general actions in the box model.
If there is a design specification oh, I also often put forward requirements to the designer, must develop a set of product design specifications.
/ / utils tools
/ / color
.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; }
/ / font
.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; }
// Text alignment
.tl {text-align: left; }
.tc {text-align: center; }
.tr {text-align: right; }
// Float and clear float
.fl {float: left; }
.fr {float: right; }
.fix {*zoom: 1; }
.fix:after{display:table; content:''; clear:both; }
/ / show
.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; }
/ / position
.pr {position: relative; }
.pa {position: absolute; }
.pf {position: fixed; }
// Box model
.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; }
// Button is disabled
.disabled{outline:0 none; cursor:default! important; opacity:.4; filter:alpha(opacity=40); -ms-pointer-events:none; pointer-events:none; }
Copy the code
Add style entry file
Finally, create an entry file and import all the style utility classes for the main program to import.
/ / index. SCSS document
// @import './varibles.scss'
@import './reset.scss';
@import './utils.scss';
Copy the code
Introduced in the varibles. SCSS vue configuration, not required here
Add index.scss directly to main.js
import '@/assets/styles/index.scss'
Copy the code
What are the techniques and aspects of writing styles in VUE?
Avoid global pollution
Write CSS/SCSS and scoped on a page. Scoped keeps the style of the page local and does not affect the style of other pages.
Bem specification
The problem that most of us have is we have too many nested styles what do we call them
BEM, short for Block, Element, modifier, is a front-end CSS naming methodology proposed by Yandex team.
The name is too long and legible
.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 {
// ...
}
}
}
}
}
}
Copy the code
Bem usage mode
block-name__element-name--color
- Discriminating blocks, child elements, modifier elements
- Block, a separate unit in a page
- Child element, the child of the block
card__item
use__
The connection - Child elements are named using – concatenation
- Modify (changeable)
card__item--warning
use--
We use BEM to transform styles
.cardbox {
&__header {
&__title {
/ /...
}
}
&__body {
&__item {
&__title {
/ /...
}
}
}
}
Copy the code
Bem generally recommends that child elements be nested within 2-3 levels
However, we found that style child elements were a little too nested, using bibarychild element nesting.
The general idea is to try to separate the parent-child relationship and treat the card itself as a block.
Let’s try to reduce nesting:
.cardbox {
&__header {
&__title {
/ /...
}
}
&__body {
.card {
&__title {
/ /...
}
}
}
}
Copy the code
Now that style writing is more efficient and more formal, HTML writing is a lot of cumbersome code.
For example, most labels open front and close back. With puG we can omit many character strokes. Let’s talk about how to write templates using PUG.
Which HTML style you prefer is anyone’s guess, but I prefer PUG, with its indentation and simplicity, to feel like WRITING SCSS.
How do I use PUG
Similar to SASS, install puG and loader of PUG first
yarn add -D pug pug-html-loader pug-plain-loader
Copy the code
Complete the configuration
module.exports = {
// ...
chainWebpack: (config) = > {
config.module
.rule('pug')
.test(/\.pug$/)
.use('pug-html-loader')
.loader('pug-html-loader')
.end()
}
}
Copy the code
Write puG code
Use SCSS tools to work perfectly with PUG and write a lot less code
/ / login
<template lang="pug">
.login
H1.login__title. ml15 Register/login
.login__form.mt15.ml15
Van-field. login__form__input(placeholder=" input "V-model ="phone")
.login__form__protocol.mt15
.login__form__protocol__tips.dib. Text-weak Consent is given by registering or logging in
.login__form__protocol__name.dib. Color -orange User Protocol
app-button.mt15(size="large"
theme="orange"
:disabled="phone.length ! 11 = ="
@click="handleSubmit"
) the next step
</template>
Copy the code
Now that we’ve introduced styles, I’ll talk about the introduction of other resources
How do you manage your resources
Principles and solutions
I temporarily divide resources into the following categories
- The font
- ICON
- The picture
- styleCreate a new directory for each of them and place them under Assets in separate categories for use elsewhere. Use alias for better rename, making it easier to access.
Add the vue.config.js configuration and set the assets alias
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
/ /...
chainWebpack: (config) = > {
config.resolve.alias.set(The '@', resolve('src')).set('@assets', resolve('src/assets'))
}
}
Copy the code
ICON
The introduction of iconfont
- Iconfont Ali icon project download, the whole project icon package download down
- The following four files are required to introduce the iconFONT style
iconfont.eot
iconfont.ttf
iconfont.woff
iconfont.woff2
- Iconfont is introduced into the project
icon
componentization
<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>
Copy the code
Introduce images as ICONS
To componentize the image, let’s write an IMG component
<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>
Copy the code
How do you manage your routes
Principles and solutions
With vue-router, use import() to generate an asynchronous route and load the module only when it is accessed.
Why does using import() load modules asynchronously?
MDN: Dynamic import() is useful when you want to load modules under certain conditions or on demand. While static imports are the best choice for initializing load dependencies, using static imports is easier to benefit from code static analysis tools and tree shaking.
To put it bluntly, it is for the purpose of loading on demand. Most implementations now rely on the import() method for loading on demand.
Install the vue – the router
yarn add vue-router
Copy the code
After installing the Router, create a page before writing the router
Create a new empty page
The views directory under the SRC directory is added to store page files. Create the Index directory and the home page
<template lang="pug">
The home page
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
Copy the code
Write the routing
const routes = [
{
/ / home page
path: '/'.
name: 'index'.
redirect: '/home'.
component: App,
children: [
{
/ / home page
path: 'home'.
name: 'home'.
// Route lazy loading
component: (a)= >
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
Copy the code
In order to eliminate # and make the path more beautiful and concise, we use history mode, but the problem with history mode is that the asynchronous route is not cached in the page, so it will not be found on the first time you enter the page
Add the configuration in vue.config.js. The development environment can access it
module.exports = {
// ...
devServer: {
historyApiFallback: true
}
}
Copy the code
There are a lot of routing can be studied to the place, you can study oh!
Componentized development
Principles and solutions
In general, we divide between base (common) components and business components based on their reuse.
To save time and speed up development, most of the base components here reference open source components. Of course, you can’t just use it.
Secondary encapsulation, or high-level component development, is typically required.
- Modify styles by modifying and overwriting the styles of the current component.
- Change the JS logic by intercepting events.
Let’s start with the Vant component
practice
The introduction of vant
yarn add vant
Copy the code
Secondary packaging and transformation of basic components
Here are 7 steps to write a common component
- Create a new
components
Directory to hold the base components - The base component is named
app-xxx
或appXxx
, create a new oneapp-button
Directory, Newindex.vue
- Design and write components according to the design draft
Design components before writing them, and write them according to their invariability and variability. Invariance is the core of a component, which can adjust the related parts of the component according to parameters to achieve optional functions.
- Implementation component
<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--The ${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>
Copy the code
:: V-deep style overwrites the component style in scoped case without changing its style
- Once you’ve written the basic component README, why document it? If multiple people are working on the same project, the underlying components will be referenced by others. Make it easy for others to use, so document it.
In short: comments or documentation are important as long as public methods and components are likely to be used by others. Take responsibility for your own code.
For other uses, see Vant
- Global reference: The underlying component is used in many pages. If you set it to global, you don’t need to reference it anywhere else.
Create a new file, global, to hold the global component registry and import it in main.js
import Vue from 'vue'
import appButton from '@/components/app-button'
Vue.component('app-button', appButton)
Copy the code
- To write good
demo
Write unit tests, even if you don’t write them yetdemo
So that it can run normally
Add demo pages and routes
<template lang="pug">
div(class="base")
// Button component
App-button.mt4 (theme="blue") confirm payment
App-button (theme="orange") confirm payment
App-button (theme=" Purple ") confirm payment
App-button.mt4 (theme="red") confirm payment
App-button (theme="grey") confirm payment
App-button. mt4(theme="blue" size="large") modify the address
App-button.mt4 (theme="orange" size="large") modify the address
App-button. mt4(theme="purple" size="large") modify the address
App-button. mt4(theme="red" size="large") modify the address
App-button. mt4(theme="grey" size="large") modify the address
App-button. mt4(theme="blue" type="minor"
App-button (theme="orange" type="minor") confirms receipt
App-button (theme="purple" type="minor"
App-button (theme="red" type="minor") Change the address
App-button (theme="grey" type="minor") Change the address
App-button.mt4 (theme="blue" type="rect"
App-button (theme="orange" type="rect") confirms receipt
App-button (theme="purple" type="rect"
App-button (theme="red" type="rect") Change the address
App-button (theme="grey" type="rect") Change the address
</template>
<script>
export default {
}
</script>
<style lang="scss">
</style>
Copy the code
Implementation effect
How to encapsulate a request
Principles and solutions
It’s basically a wrapper around Axios, and the wrapper serves two main purposes.
- Modify some basic configuration: address request, timeout, other miscellaneous
- Unified operation: unified handling of errors, unified handling of request parameters and formats, unified response parameters and formats. Unified processing of messages, unified interception of mounts, and so on.
There are many similar articles on the web, but here are my common encapsulation schemes.
practice
Set the request address based on the environment
/ / env - default. Js file
// Different environments access different paths
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']
Copy the code
Since mock environments are not necessarily the same for everyone who develops them, this file suggests gitignore ignore them. Templates can be written in a readme document and added to the file when the project is started.
Create a newutils
tool
We now wrap AXIos into our own configuration, and then define four common request methods to call
/ / utils/HTTP js file
import axios from 'axios'
import { baseURL } from '.. /.. /.env-defalut.js'
/ / axios configuration
const defaultBaseUrl = 'http://localhost:8080/'
// Default timeout period
axios.defaults.timeout = 15000
// Unified configuration of data interface domain name. env
axios.defaults.baseURL = baseURL || defaultBaseUrl
// HTTP request interceptor
axios.interceptors.request.use(
(config) = > {
config.headers = {
}
return config
},
(err) => {
return Promise.reject(err)
}
)
// HTTP Response interceptor
axios.interceptors.response.use(
(response) = > {
return response
},
(error) => {
const data = error.response.data
return Promise.reject(data || error)
}
)
export default axios
/ * *
* Fetch request method
* @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 request method, send data format 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 request method, send data format 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)
}
)
})
}
Copy the code
How to manage apis
The principle of
The first thing to do is to lay out the principles of an API. My principles are generally these:
- Clean and pure
- Try not to deal with data
- Don’t rely on each other
The advantage is that you don’t process data in the API, the interface in the API is the same as the interface documentation. To avoid people referring to my API and looking at the code, just look at the documentation.
Example: Imagine a situation where someone references my API and suddenly realizes that the response data is wrong. First it checks to see that the page data has not changed. After reading the API document, I found that there was no problem with the data. Finally, I found that I had processed the API when I was writing it, but the API could not be changed, which affected my own module. It’s just rewriting an API, which is messy and not clean and elegant.
import { fetch, post } from '@/utils/http'
// The user logs in
export const login = data= > post('/user/login', data)
// Get user information
export const getUserInfo = (data) = > fetch('/api/user/info', data)
Copy the code
If you need to process data, either use an intermediate tool or process it inside the page. Of course, it’s a practical problem.
How to usemock
Simulated data
Principles and solutions
Generally, there are two solutions: one is to simulate the back end and use a remote online JSON server. Another option is to build native JSON or use an off-the-shelf Node server to intercept requests.
Each of these two ways has its strengths and weaknesses. There is no superior or inferior.
The remote onlinemock
Remote online mock I’ve used
- Apizza: Easy to use, fully featured, like his file expansion directory
api
The free version only supports 2 co-editors - Swagger: Open source and free,
api
Management is too messy, - Rap/RAP2: Open source, free, can build local
api
, you need to build your own
Advantages of using remote Mocks:
- It does not need to be added within the project
mock
- Function more comprehensive improvement
- Can be based on the interface documentation
mock
, together with the interface document for easier viewing.
Disadvantages: You need to build your own server, only supports static mocks, cannot be used with unit tests
Local JSON mock
- use
webpack
Internal Mock configuration
devServer: {
// Mock if the interface is not implemented
before: require('./mock')
}
Copy the code
Basic principle: Basically, node reads the file, converts it to JSON format, mocks the data using mock.js, and finally Webpack intercepts the request to generate JSON response data
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((a)= > {
var json
if (/\.json$/.test(datafile)) {
// Json files expose mock templates
json = getJsonFile(datafile)
} else if (/\.js$/.test(datafile)) {
json = require(datafile)(req.query)
}
res.json(Mock.mock(json))
}, 500)
}
}
Copy the code
- use
json-server
The construction is mainly divided into the following steps
npm
The installationjson-server
- write
npm
Script command, importmock
The configuration file - write
mock
Route matching rule
Relatively simple here do not describe in detail!
The disadvantage of being local is the need
- The front-end needs to be based on
api
Document writingmock
The data format - No remote function
mock
So perfect, supportrestful
It needs to be researched - Also need configuration related
mock
tool
Advantage is that
- You don’t have to look at the edit
api
The document - It can be changed and viewed in the code
mock
data - Support the use of
JavaScipt
Dynamic placemock
Can be used in conjunction with unit tests
conclusion
This article cost the author more than a week of spare time, save hand typing 6000+ words, at the same time collect, sort out many previous skills and writing while thinking and summary. If it helps you, that’s its greatest value. I can’t get over it if I don’t like it! 😄
Due to the limited technical level, if there is any mistake in the article, please point out in the comment area, thank you!
Most of the code in this article will be updated in Suo-Design-Pro
The project will be perfected as much as possible
Writing practical summaries is really time consuming. How to share the place that helps you in the article, let more people see!
The next section is a preview
- How to write native components, and the thinking and principles of component writing?
- How to use VUEX and its application scenarios and principles
- How to use filters and write your own filters
- How to use Jest to test your code? Comparison of TDD and BDD
Click to jump to the next section
The resources
- commitizen
- MDN import()
- Vant document
- Eslint document
- Vue – the router documentation
- Sass document
- Axios document
The open source project
The above function configuration will be implemented in SUO-Design-Pro, hope you can continue to pay attention to!
This article is formatted using MDNICE