Skip to content

Latest commit

 

History

History
1092 lines (805 loc) · 19.1 KB

分享-王.md

File metadata and controls

1092 lines (805 loc) · 19.1 KB

网络请求

在写网络请求的时候,如果我们经常写

const res = this.$axios.get('/api')
this.data = res.data

这样的代码的话,在写了很多之后维护或修改都会变得非常的困难,并且会出现很多重复代码,这是后适当的对网络请求进行封装就变得很重要了。

准备工作

axios

qs 序列化

文件目录

src
 └── services
     ├── api.js // api管理
     ├── axios.js //axios配置
     └── http.js //请求封装

axios.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

/**
 * 封装请求方法
 */
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

/**
 * 所有的接口请求
 */

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)
}

或用 vuexactions进一步封装

actions: {
    [FETCH_USER_INFO]({ commit }, id) {
      const { data } = await userInfo({ id });
      commit(SET_USER_INFO, data)
    },
  },
      

这样只使用一次actions就可以同时发送请求和处理数据了

数据提交

本来这个很简单没什么可说的 但是前几天还是踩了个坑 提交的时候需要注意下Content-Type

1、Content-Type: application/json

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

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

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

/*! 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

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 使用 --
.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;

JS

单个 if 语句优化策略

优化前

function log() {
  console.log('前面的flag为真,就会看到我');
}
let flag = true;

if (flag) {
  log();
}

优化后

function log() {
  console.log('前面的flag为真,就会看到我');
}

let flag = true;

flag && log();

单个普通if else优化策略

优化前

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 }

map代替for

假设接口返回这样一个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,
}));

简洁明了

Vue

模块按需加载

写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]开头的组件就可以全局使用了

@hook

假设我们有一个loding组件 在某个子组件beforeUpdate 时开始 loadingupdated 之后停止 loading

最简单的方法就是改写组件的生命周期函数,使其在 mounted/beforeUpdata /updatad 时通知父组件显示或者隐藏 loading。

有没有更方便的写法呢 当然有

<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

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,
  },
});

使用mutationTypesactionTypes这样在写的时候会有代码提示,防止出错

mutationTypes.js

export const SET_USER_INFO = 'SET_USER_INFO';

actionTypes.js

export const FETCH_USER_INFO = 'FETCH_USER_INFO';

user.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为例)

//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'));
  },
};

其他的一些配置 vue.config.js

publicPath

部署应用包时的基本 URL

publicPath: process.env.NODE_ENV === 'production' ? '/game/xzxjbbm2020/' : './',

outputDir

当运行 vue-cli-service build 时生成的生产环境构建文件的目录

outputDir : 'build'

productionSourceMap

productionSourceMap : false

规范git提交

插件

  • commitizen

commit

git cz 

arxlqI.png

直接选择就可以了

实用网站推荐

一键AI抠图

www.remove.bg/zh

配色网站 colorhunt

http://www.colorhunt.co/

as1S7q.png

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请求

[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]

前端代码优化实用篇

axios POST提交数据的三种请求方式写法

CSS Tricks

Vue CLI

吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧《上》

吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧《中》

10个简单的技巧让你的 vue.js 代码更优雅🍊