# 网络请求 在写网络请求的时候,如果我们经常写 ```js const res = this.$axios.get('/api') this.data = res.data ``` 这样的代码的话,在写了很多之后维护或修改都会变得非常的困难,并且会出现很多重复代码,这是后适当的对网络请求进行封装就变得很重要了。 ## 准备工作 `axios` `qs` 序列化 ## 文件目录 ```js src └── services ├── api.js // api管理 ├── axios.js //axios配置 └── http.js //请求封装 ``` ## `axios.js` ```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; ``` ## `http.js` ```js /** * 封装请求方法 */ 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}`); }); }); } ``` ## `api.js` ```js /** * 所有的接口请求 */ import { get } from './http'; export const hotQuestion = () => get('/hot'); /** * * @param {*} id 用户id */ export const userInfo = (id) => get('/user',{id}) ``` ## 使用 ```js import { hotQuestion } from '@/services/api' async getHotQuestion() { const { data } = await hotQuestion(params) } ``` 或用 `vuex` 的`actions`进一步封装 ```js actions: { [FETCH_USER_INFO]({ commit }, id) { const { data } = await userInfo({ id }); commit(SET_USER_INFO, data) }, }, ``` 这样只使用一次actions就可以同时发送请求和处理数据了 # 数据提交 本来这个很简单没什么可说的 但是前几天还是踩了个坑 提交的时候需要注意下`Content-Type` ## 1、Content-Type: application/json ```js import axios from 'axios' let data = {"code":"1234","name":"yyyy"}; axios.post(`${this.$url}/test/testRequest`,data) .then(res=>{ console.log('res=>',res); }) ```  ## 2、Content-Type: multipart/form-data ```js 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); }) ```  ## 3、Content-Type: application/x-www-form-urlencoded ```js 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); }) ```  # CSS ## reset.css ### Normalize.css ```css /*! 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; } ``` ### 去掉默认padding和margin ```css 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规范 > BEM是块(block)、元素(element)、修饰符(modifier)的简写,由 Yandex 团队提出的一种前端 CSS 命名方法论。 就是一种class的命名方法 `block-name__element-name--color` - 子元素,块里面的儿子 `card__item` 使用 `__` 连接 - 子元素长命名使用 - 连接 - 修饰(易变的)`card__item--warning` 使用 `--` ```scss .cardbox { &__header { &__title { } } &__body { .card { &__title { } } } } ``` 这样结构更加清晰 > bem 一般推荐子元素嵌套尽量在2-3层以内 ## 文字省略号 注意容器的宽度是必须的 ### 单行文字 ```scss .article-container { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } ``` ### 多行文字 ```scss .article-container {s display: -webkit-box; word-break: break-all; -webkit-box-orient: vertical; -webkit-line-clamp: 4; //需要显示的行数 overflow: hidden; text-overflow: ellipsis; } ``` ## 消除图片下方间隙 ```SCSS vertical-align: top; ``` # JS ## 单个 if 语句优化策略 优化前 ```js function log() { console.log('前面的flag为真,就会看到我'); } let flag = true; if (flag) { log(); } ``` 优化后 ```js function log() { console.log('前面的flag为真,就会看到我'); } let flag = true; flag && log(); ``` ## 单个普通if else优化策略 优化前 ```js function demo(flag) { if (flag) { return '真'; } else { return '假'; } } ``` 优化后 ```js function demo(flag) { return flag ? '真' : '假'; } ``` ## 数组去重 ```js 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' ] ``` ## 简单深拷贝对象 ```js 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 } ``` ## map代替for 假设接口返回这样一个json数据 ```js const data = [ { name: 'wjx', age: '19', stuNum: '2019211000', }, { name: 'wxj', age: '20', stuNum: '2019211001', }, { name: 'xjw', age: '21', stuNum: '2019211001', }, ]; ``` 现在我们需要一个user对象数组,每个对象只需要name和age两个字段,怎么获取 优化前 ```js const user = []; for (i = 0; i < data.length; i++) { const { name, age } = data[i]; user.push({ name, age }); } ``` 很简单 但是这样写很不优雅! 优化后 ```js const user = data.map(item => ({ name: item.name, age: item.age, })); ``` 简洁明了 # Vue ## 模块按需加载 写router时,一般会这样写 ```js import MyComponent from '@/components/MyComponent' routes: [ { // ... component : MyComponent, } ] ``` 这样写虽然没有错,但是所有模块会在首页加载时都进行加载,延长加载时间 而使用`import()` 生成异步路由,只有在访问时候才会加载模块,达到**按需加载**的目的 ```js routes: [ { // ... component : () => import('@/components/MyComponent'), } ] ``` ## 注册全局组件 新建一个文件 `global.js` 存放全局组件注册,在 `main.js` 引入 ```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 ) }) ``` ```js // main.js import './global'; ``` 这样以V[A-Z]开头的组件就可以全局使用了 ## @hook 假设我们有一个loding组件 在某个子组件`beforeUpdate` 时开始 `loading`。`updated` 之后停止 `loading`。 最简单的方法就是改写组件的生命周期函数,使其在 `mounted/beforeUpdata /updatad` 时通知父组件显示或者隐藏 loading。 有没有更方便的写法呢 当然有 ```js <v-chart @hook:beforeUpdated="loading = true" @hook:updated="loading = false" :data="data" /> ``` 这样,就实现了对子组件生命周期的监听。对任意的组件都有效果,包括引入的第三方组件。 ## .sync 当你有需要在子组件修改父组件值的时候这个方法很好用  ## vuex - 分模块管理 ### 文件目录 ``` store ├── actionTypes.js ├── index.js ├── modules │ └── user.js └── mutationTypes.js ``` ### `index.js` ```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`这样在写的时候会有代码提示,防止出错 ### `mutationTypes.js` ```js export const SET_USER_INFO = 'SET_USER_INFO'; ``` ### `actionTypes.js` ```js export const FETCH_USER_INFO = 'FETCH_USER_INFO'; ``` ### `user.js` ```js 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 CLI ## 自动导入css变量(以sass为例) ```js //vue.config.js module.exports = { sourceMap: true, css: { loaderOptions: { scss: { prependData: `@import "~@/assets/style/variables.scss";`, }, }, }, }; ``` 这样就可以`variables.scss`中定义的变量就变成了全局变量 ## 环境变量 `process.env.VUE_APP_BASE_API`就是自定义的环境变量,使用环境变量能在不同环境下使用不同的配置 ```sh .env # 在所有的环境中被载入 .env.local # 在所有的环境中被载入,但会被 git 忽略 .env.[mode] # 只在指定的模式中被载入 .env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略 常用 ``` 在`env.production.local`中 ```js VUE_APP_BASE_API = 'https://wx.redrock.team/wxapi/xxx' ``` 在`env.development.local`中 ``` VUE_APP_BASE_API = '/api' ``` 这样实现了在开发环境和生产环境接口的切换 当然也可以使用 ```js const API = process.env.NODE_ENV === 'production' ? 'https://wx.redrock.team' : '/api1' ``` 这种写法来变相实现环境变量 看个人的喜好 ## 配置别名 ```js 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')); }, }; ``` ## 其他的一些配置 vue.config.js ### publicPath 部署应用包时的基本 URL ```js publicPath: process.env.NODE_ENV === 'production' ? '/game/xzxjbbm2020/' : './', ``` ### outputDir 当运行 `vue-cli-service build` 时生成的生产环境构建文件的目录 ```js outputDir : 'build' ``` ### productionSourceMap ```js productionSourceMap : false ``` # 规范git提交 ## 插件 - commitizen ## commit ``` git cz ```  直接选择就可以了 # 实用网站推荐 ## 一键AI抠图 www.remove.bg/zh  ## 配色网站 colorhunt http://www.colorhunt.co/  ## Font Awesome 图标字体 https://fa5.dashgame.com/#/ 一些小图标用起来还是不错的 ## CSS Tricks 神奇的CSS http://css-tricks.neatbang.com/ ## cdnjs https://cdnjs.com/libraries ## 各种vue组件库 http://vue.awesometiny.com/ # ref [更优雅的HTTP请求](https://juejin.im/post/6844904100547526670) [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] [前端代码优化实用篇](https://juejin.im/post/6844904126057283592) [axios POST提交数据的三种请求方式写法](https://segmentfault.com/a/1190000015261229) [CSS Tricks](http://css-tricks.neatbang.com/) [Vue CLI](https://cli.vuejs.org/zh/guide/) [吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧《上》](https://juejin.im/post/6844904034663399437) [吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧《中》](https://juejin.im/post/6844903972050829320) [10个简单的技巧让你的 vue.js 代码更优雅🍊](https://juejin.im/post/6854573215969181703)