在写网络请求的时候,如果我们经常写
const res = this.$axios.get('/api')
this.data = res.data
这样的代码的话,在写了很多之后维护或修改都会变得非常的困难,并且会出现很多重复代码,这是后适当的对网络请求进行封装就变得很重要了。
axios
qs
序列化
src
└── services
├── api.js // api管理
├── axios.js //axios配置
└── http.js //请求封装
/**
* axios配置
*/
import axios from 'axios';
axios.defaults.baseURL = process.env.VUE_APP_BASE_API;
axios.defaults.timeout = 6000;
// http request 拦截器
axios.interceptors.request.use(
config => {
config.headers = {
};
return config;
},
err => {
return Promise.reject(err);
},
);
// http response 拦截器
axios.interceptors.response.use(
res => {
return res;
},
err => {
return Promise.reject(err);
},
);
export default axios;
/**
* 封装请求方法
*/
import axios from './axios';
export function get(url, params = {}) {
return axios.get(url, { params }).catch(error => {
throw new Error(error);
});
}
export function post(url, data = {}, config = {}) {
return axios.post(url, data, config).catch(error => {
throw new Error(error);
});
}
export function patch(url, data = {}, config = {}) {
return axios.patch(url, data, config).catch(error => {
throw new Error(error);
});
}
export function put(url, data) {
return axios.put(url, data).catch(error => {
throw new Error(error);
});
}
export function del(url) {
return axios.del(url).catch(error => {
throw new Error(`[RWV] ApiService ${error}`).catch(error => {
throw new Error(`[RWV] ApiService ${error}`);
});
});
}
/**
* 所有的接口请求
*/
import { get } from './http';
export const hotQuestion = () => get('/hot');
/**
*
* @param {*} id 用户id
*/
export const userInfo = (id) => get('/user',{id})
import { hotQuestion } from '@/services/api'
async getHotQuestion() {
const { data } = await hotQuestion(params)
}
或用 vuex
的actions
进一步封装
actions: {
[FETCH_USER_INFO]({ commit }, id) {
const { data } = await userInfo({ id });
commit(SET_USER_INFO, data)
},
},
这样只使用一次actions就可以同时发送请求和处理数据了
本来这个很简单没什么可说的 但是前几天还是踩了个坑 提交的时候需要注意下Content-Type
import axios from 'axios'
let data = {"code":"1234","name":"yyyy"};
axios.post(`${this.$url}/test/testRequest`,data)
.then(res=>{
console.log('res=>',res);
})
import axios from 'axios'
let data = new FormData();
data.append('code','1234');
data.append('name','yyyy');
axios.post(`${this.$url}/test/testRequest`,data)
.then(res=>{
console.log('res=>',res);
})
import axios from 'axios'
import qs from 'Qs'
let data = {"code":"1234","name":"yyyy"};
axios.post(`${this.$url}/test/testRequest`,qs.stringify({
data
}))
.then(res=>{
console.log('res=>',res);
})
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;}
BEM是块(block)、元素(element)、修饰符(modifier)的简写,由 Yandex 团队提出的一种前端 CSS 命名方法论。
就是一种class的命名方法
block-name__element-name--color
- 子元素,块里面的儿子
card__item
使用__
连接 - 子元素长命名使用 - 连接
- 修饰(易变的)
card__item--warning
使用--
.cardbox {
&__header {
&__title {
}
}
&__body {
.card {
&__title {
}
}
}
}
这样结构更加清晰
bem 一般推荐子元素嵌套尽量在2-3层以内
注意容器的宽度是必须的
.article-container {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.article-container {s
display: -webkit-box;
word-break: break-all;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4; //需要显示的行数
overflow: hidden;
text-overflow: ellipsis;
}
vertical-align: top;
优化前
function log() {
console.log('前面的flag为真,就会看到我');
}
let flag = true;
if (flag) {
log();
}
优化后
function log() {
console.log('前面的flag为真,就会看到我');
}
let flag = true;
flag && log();
优化前
function demo(flag) {
if (flag) {
return '真';
} else {
return '假';
}
}
优化后
function demo(flag) {
return flag ? '真' : '假';
}
const arr = [1, 2, 1, 3, '1', '2', '2'];
console.log(Array.from(new Set(arr))) // [ 1, 2, 3, '1', '2' ]
console.log([...new Set(arr)]) // [ 1, 2, 3, '1', '2' ]
const obj = {
name: 'wjx',
age: 19,
};
const cloneObj = JSON.parse(JSON.stringify(obj));
cloneObj.name = 'xjw';
console.log(cloneObj); // { name: 'xjw', age: 19 }
console.log(obj); // { name: 'wjx', age: 19 }
假设接口返回这样一个json数据
const data = [
{
name: 'wjx',
age: '19',
stuNum: '2019211000',
},
{
name: 'wxj',
age: '20',
stuNum: '2019211001',
},
{
name: 'xjw',
age: '21',
stuNum: '2019211001',
},
];
现在我们需要一个user对象数组,每个对象只需要name和age两个字段,怎么获取
优化前
const user = [];
for (i = 0; i < data.length; i++) {
const { name, age } = data[i];
user.push({ name, age });
}
很简单 但是这样写很不优雅!
优化后
const user = data.map(item => ({
name: item.name,
age: item.age,
}));
简洁明了
写router时,一般会这样写
import MyComponent from '@/components/MyComponent'
routes: [
{
// ...
component : MyComponent,
}
]
这样写虽然没有错,但是所有模块会在首页加载时都进行加载,延长加载时间
而使用import()
生成异步路由,只有在访问时候才会加载模块,达到按需加载的目的
routes: [
{
// ...
component : () => import('@/components/MyComponent'),
}
]
新建一个文件 global.js
存放全局组件注册,在 main.js
引入
import Vue from 'vue'
const requireComponent = require.context(
// 其组件目录的相对路径
'./components',
// 是否查询其子目录
false,
// 匹配基础组件文件名的正则表达式
/V[A-Z]\w+\.(vue|js)$/
)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = fileName.split('/').pop().replace(/\.\w+$/, '')
// 全局注册组件
Vue.component(
componentName,
// 如果这个组件选项是通过 `export default` 导出的,
// 那么就会优先使用 `.default`,
// 否则回退到使用模块的根。
componentConfig.default || componentConfig
)
})
// main.js
import './global';
这样以V[A-Z]开头的组件就可以全局使用了
假设我们有一个loding组件 在某个子组件beforeUpdate
时开始 loading
。updated
之后停止 loading
。
最简单的方法就是改写组件的生命周期函数,使其在 mounted/beforeUpdata /updatad
时通知父组件显示或者隐藏 loading。
有没有更方便的写法呢 当然有
<v-chart
@hook:beforeUpdated="loading = true"
@hook:updated="loading = false"
:data="data"
/>
这样,就实现了对子组件生命周期的监听。对任意的组件都有效果,包括引入的第三方组件。
当你有需要在子组件修改父组件值的时候这个方法很好用
- 分模块管理
store
├── actionTypes.js
├── index.js
├── modules
│ └── user.js
└── mutationTypes.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
Vue.use(Vuex);
export default new Vuex.Store({
//在非生产环境下,使用严格模式
strict: process.env.NODE_ENV !== 'production',
modules: {
user,
},
});
使用mutationTypes
和actionTypes
这样在写的时候会有代码提示,防止出错
export const SET_USER_INFO = 'SET_USER_INFO';
export const FETCH_USER_INFO = 'FETCH_USER_INFO';
import { SET_USER_INFO } from '../mutationTypes';
import { FETCH_USER_INFO } from '../actionTypes';
import { userInfo } from '@/services/api';
export default {
state: {
user: {},
},
mutations: {
[SET_USER_INFO](state, user) {
state.user = user;
},
},
actions: {
[FETCH_USER_INFO]({ commit }, id) {
const { data } = await userInfo({ id });
commit(SET_USER_INFO, data)
},
},
getters: {
user(state) {
return state.user
}
}
};
//vue.config.js
module.exports = {
sourceMap: true,
css: {
loaderOptions: {
scss: {
prependData: `@import "~@/assets/style/variables.scss";`,
},
},
},
};
这样就可以variables.scss
中定义的变量就变成了全局变量
process.env.VUE_APP_BASE_API
就是自定义的环境变量,使用环境变量能在不同环境下使用不同的配置
.env # 在所有的环境中被载入
.env.local # 在所有的环境中被载入,但会被 git 忽略
.env.[mode] # 只在指定的模式中被载入
.env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略 常用
在env.production.local
中
VUE_APP_BASE_API = 'https://wx.redrock.team/wxapi/xxx'
在env.development.local
中
VUE_APP_BASE_API = '/api'
这样实现了在开发环境和生产环境接口的切换
当然也可以使用
const API = process.env.NODE_ENV === 'production' ? 'https://wx.redrock.team' : '/api1'
这种写法来变相实现环境变量 看个人的喜好
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'));
},
};
部署应用包时的基本 URL
publicPath: process.env.NODE_ENV === 'production' ? '/game/xzxjbbm2020/' : './',
当运行 vue-cli-service build
时生成的生产环境构建文件的目录
outputDir : 'build'
productionSourceMap : false
- commitizen
git cz
直接选择就可以了
一些小图标用起来还是不错的
http://css-tricks.neatbang.com/
[axios封装,更好的管理和使用api接口][https://blog.langting.top/archives/73.html#toc-%E9%80%9A%E8%BF%87%E5%B0%81%E8%A3%85%E7%9A%84axios]
吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧《上》