Lison《vue技术栈开发实战》(三)
Ajax请求实战
解决跨域问题
什么是跨域:
之前提到过解决跨域的问题可以设置代理:
这个配置会将所有的未找到文件的请求请求代理到proxy指向的路径下面,避免了跨域的问题。
第二种方法是在后端设置一些header值来解决跨域。
只需要在后端设置三个字段值,前端不需要做代理就可以实现跨域。
封装axios
抽离url
封装
import axios from 'axios'
import { baseURL } from '@/config'
class HttpRequest {
constructor (baseUrl = baseURL) {
this.baseUrl = baseUrl
this.queue = {}
}
getInsideConfig () {
const config = {
baseURL: this.baseUrl,
headers: {
//
}
}
return config
}
distroy (url) {
delete this.queue[url]
if (!Object.keys(this.queue).length) {
// Spin.hide()
}
}
interceptors (instance, url) {
instance.interceptors.request.use(config => {
// 添加全局的loading...
if (!Object.keys(this.queue).length) {
// Spin.show()
}
this.queue[url] = true
return config
}, error => {
return Promise.reject(error)
})
instance.interceptors.response.use(res => {
this.distroy(url)
const { data, status } = res
return { data, status }
}, error => {
this.distroy(url)
return Promise.reject(error)
})
}
request (options) {
const instance = axios.create()
options = Object.assign(this.getInsideConfig(), options)
this.interceptors(instance, options.url)
return instance(options)
}
}
export default HttpRequest
请求拦截
响应拦截
队列管理
将所有的请求压入栈,如果队列为空则说明所有的请求已经结束
使用Mock模拟Ajax请求
mock主要用来模拟请求,在main.js中引入mock
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Bus from './lib/bus'
if (process.env.NODE_ENV !== 'production') require('./mock')
Vue.config.productionTip = false
Vue.prototype.$bus = Bus
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
响应模拟
mock的index文件进行拦截,当发现请求时调用对应的方法
Mock用法精讲
数据模板
可以看一下官方对模板的DTD:模板语言
Random方法大全
占位符
占位符
看下使用示理:
import Mock from 'mockjs'
const Random = Mock.Random
export const getUserInfo = (options) => {
const template = {
'str|2-4': 'lison',
'name|5': 'lison',
'age|+2': 18,
'num|4-10': 0,
'float|3-10.2-5': 0,
'bool|1': true,
'bool2|1-9': true, // min/(min+max)
'obj|2': {
a: 'aa',
b: 'bb',
c: 'cc'
},
'obj2|1-2': {
a: 'aa',
b: 'bb',
c: 'cc'
},
'arr|2-4': [1, 2, 3],
'arr2|2': ['a', 'b'],
'func': () => {
return 'this is created by function'
},
'reg': /[1-9][a-z]/,
email: Mock.mock('@email'),
range: Random.range(3, 10, 2),
date: Random.date('yyyy-MM-dd'),
time: Random.time('hh:mm'),
datetime: Random.datetime('yyyy-MM-dd hh:mm'),
now: Random.now('hour', 'yyyy-MM-dd a hh:mm'),
img: Random.image('100x200', '#00ff00', '#ffffff', 'png', 'Lison'),
img_base64: Random.dataImage(),
color: Random.color(),
cword: Random.cword('玩儿螺丝刀', 2, 5),
cname: Random.cname(),
email2: Random.email('lison.com'),
region: Random.region(),
province: Random.province(),
city: Random.city(true),
county: Random.county(true),
zip: Random.zip(),
upperFirstLetter: Random.capitalize('lison'),
pick: Random.pick([1, 2, 3, 4]),
shuffle: Random.shuffle([1, 2, 3, 4]),
guid: Random.guid(),
fruit: Random.fruit(),
fruit2: '@fruit'
}
return Mock.mock(template)
}
Vue中第三方JS库的使用
组件封装基础
传入参数通过prop的方式,如果数据是number、string和布尔类型的,直接传入值就可以了,如果是object、array和数组,默认值需要传入一个函数,这个函数return一个对应的类型
组件中使用ID值
this._uid
能获取唯一id,全局自增变化
获取DOM或组件实例
ref获取,如果定义在组件上就是获取组件实例,如果定义在标签上就是获取dom元素
封装一个数字渐变CountTo组件
cont-to.vue
<template>
<div>
<slot name="left"></slot><span ref="number" :class="countClass" :id="eleId"></span><slot name="right"></slot>
</div>
</template>
<script>
import CountUp from 'countup'
export default {
name: 'CountTo',
computed: {
eleId () {
return `count_up_${this._uid}`
},
countClass () {
return [
'count-to-number',
this.className
]
}
},
data () {
return {
counter: {}
}
},
props: {
/**
* @description 起始值
*/
startVal: {
type: Number,
default: 0
},
/**
* @description 最终值
*/
endVal: {
type: Number,
required: true
},
/**
* @description 小数点后保留几位小数
*/
decimals: {
type: Number,
default: 0
},
/**
* @description 动画延迟开始时间
*/
delay: {
type: Number,
default: 0
},
/**
* @description 渐变时长
*/
duration: {
type: Number,
default: 1
},
/**
* @description 是否使用变速效果
*/
useEasing: {
type: Boolean,
default: false
},
/**
* @description 是否使用变速效果
*/
useGrouping: {
type: Boolean,
default: true
},
/**
* @description 分组符号
*/
separator: {
type: String,
default: ','
},
/**
* @description 整数和小数分割符号
*/
decimal: {
type: String,
default: '.'
},
className: {
type: String,
default: ''
}
},
methods: {
getCount () {
return this.$refs.number.innerText
},
emitEndEvent () {
setTimeout(() => {
this.$nextTick(() => {
this.$emit('on-animation-end', Number(this.getCount()))
})
}, this.duration * 1000 + 5)
}
},
watch: {
endVal (newVal, oldVal) {
this.counter.update(newVal)
this.emitEndEvent()
}
},
mounted () {
this.$nextTick(() => {
this.counter = new CountUp(this.eleId, this.startVal, this.endVal, this.decimals, this.duration, {
useEasing: this.useEasing,
useGrouping: this.useGrouping,
separator: this.separator,
decimal: this.decimal
})
setTimeout(() => {
this.counter.start()
this.emitEndEvent()
}, this.delay)
})
}
}
</script>
<style lang="less">
@import './count-to.less';
</style>