前言
来公司实习这段时间,算是自己正真的做了一个项目(内容洞察),虽说是老项目的新需求吧,但是我还是用了自己学习的很多技术,比如说对axios的二次封装、对环境变量的封装、对工具函数的封装等等,也遇到了很多的问题,比如用element的uplod组件对文件进行上传时,回显图片的问题(以前写项目的时候都是上传图片后台会返回给我一个地址,然后我回显到当前文件列表中,但是这个项目要求的是上传图片后不立刻调用接口,而是要等用户点击确定后才上传,那么回显图片就成了问题),调用接口的时候请求头是multiparty/formData格式的问题等等
技术总结
axios的封装
感悟:
在封装axios的时候也遇到了一个问题,因为后端的接口会用到application/json application/x-www-form-urlencoded application/multipart/formdata 这三种格式的请求头,我的想法是创建3个单独的实例,然后单独的设置请求头,(至于3个js文件的公公共部分我想抽离的,但是试了好久,都以失败告终,然后就暂时放弃,),这种方法我在自己的demo中测试过是可行的,但是到了这个项目,却发现全局的axios都被影响了,弄了好久,查官方文档,百度都被我翻烂了,都无济于事,在第二天我突然想到,会不会是axios版本的问题,果然,是版本的问题,老的版本虽然可以单独创建实例,但是修改请求头的类型会影响全局的axios请求,至于开始为什么不往这方面想呢,想着这个项目应该不算很老,单独创建实例也生效,没想到啊~~
总结
下次遇到类似问题,先去官网、网上查看一下当前版是否支持该种写法
代码
这里只是罗列了一个文件,其他的2个文件都一样只不过请求头变了一下(个人感觉这样的写法还是冗余,等找到好的方法再来分享)
import axios from 'axios'
import config from '../config/index'
import Qs from 'qs'
import { getToken } from '@/utils/auth'
let instance = axios.create({
baseURL: config.baseApi,
timeout: 8000
})
instance.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'
instance.defaults.transformRequest = (data, headers) => {
console.log(data)
console.log(headers)
const contentType = headers['Content-Type']
if (contentType === 'application/x-www-form-urlencoded') {
return Qs.stringify(data)
}
}
instance.interceptors.request.use((request) => {
const headers = request.headers
if (!headers.Authorization) headers.Authorization = getToken()
return request
})
instance.interceptors.response.use(
(response) => {
console.log(response, '===>response')
return response.data
},
(resaon) => {
return Promise.reject(resaon)
}
)
function request(options) {
options.method = options.method || 'get'
if (options.method.toLowerCase() === 'get') {
options.params = options.data
}
console.log(options.mock)
if (typeof options.mock !== 'undefined') {
config.mock = options.mock
}
if (config.env === 'production') {
instance.defaults.baseURL = config.baseApi
} else {
instance.defaults.baseURL = config.mock ? config.mockApi : config.baseApi
}
console.log(options, 'options')
return instance(options)
}
;['get', 'post', 'put', 'delete', 'patch'].forEach((item) => {
request[item] = (url, data, options) => {
return request({
url,
data,
method: item,
...options
})
}
})
export default request
环境的封装
感悟
这里要说一下,用到了mock数据,这个我以前也是不了解的,来了这个公司也听别人说过,但是还是模棱两可,主要原因是没接触过。直到在课上的项目老师讲了,并且项目中用了才有所了解。所谓mock,就是自己模拟后端接口做的假数据,当实际开发的时候前后端是分离的,后端会先将api文档给前端,然后前端在根据文档mock数据,到最后联调的时候只需要将mock接口换成后端接口即可
const env = process.env.NODE_ENV || 'production'
const baseApi = process.env.VUE_APP_BASE_API
console.log(process.env, 'env')
const EnvConfig = {
development: {
baseApi: baseApi,
mockApi:
'https://console-mock.apipost.cn/app/mock/project/d4a9c329-67d4-4f51-8237-414b7d5234ee'
},
test: {
baseApi: '/',
mockApi: ''
},
production: {
baseApi: baseApi,
mockApi: ''
}
}
export default {
env,
mock: false,
...EnvConfig[env]
}
调用接口的封装
感悟
最开始的时候就是想将请求单独拎出来(学习的课上就是这么写的),然年跟师傅讨论了一下,师傅说,这是老项目到时候遇到了问题不好调试,然后我就没这么写,直到项目第一次上线遇到了前面axios封装的问题,组长说你想要代码清爽点可以使用这种方法,然后就换回来了,每个页面的请求都单独放到了一个js文件中,直接在需要的页面引入即可。
import request from '@/views/newDMP/mediaAnalyse/utils/request'
import requestJson from '@/views/newDMP/mediaAnalyse/utils/requestJson'
export default {
initDataApp(data) {
return requestJson({
method: 'post',
url: '/app/manage/queryAppListByPage',
data,
mock: false
})
},
confirmMonitor(data) {
return requestJson({
method: 'post',
url: '/app/manage/batchMonit',
data,
mock: false
})
},
cancelMonitor(data) {
return requestJson({
method: 'post',
url: '/app/manage/batchCancelMonit',
data,
mock: false
})
},
问题总结
图片回显
感悟
基于element的upload上传文件的时候,以前写项目的时候,当上传图片后,会立刻调用action的地址,然后返回给我一个地址,然后我回显到当前文件列表中,但是这个项目要求的是上传图片后不立刻调用接口,而是要等用户点击确定后才上传,那么回显图片就成了问题,
解决
在el-upload的钩子中拿到当前上传的文件流,然后用函数将file文件流转换成url地址,本来是将文件流转换成base64格式的但是file-list不支持,然后后端要求在用户编辑的时候没有修改图片就随便传一个文件流,于是我将一个图片用import的方式引入,这种方式引入的文件是base64格式的,然后我用一个函数将base64文件转化成file流
代码
<el-upload
ref="productImgRef"
action="action"
list-type="picture-card"
:before-upload="beforeUpload"
:file-list="imgFileList"
>
</el-upload>
beforeUpload(file) {
console.log(file)
if (this.imgType.indexOf(file.type) === -1) {
this.$message.info('请上传jpeg、jpg、png类型的图片')
return
}
if (file.size > this.fileSize) {
this.$message.info('图片大小需在1M以内')
return
}
console.log(getfilesize(file.size))
this.dataForm.image = file
this.dataForm.type = 1
const url = getObjectURL(file)
console.log(getObjectURL(file))
this.imgFileList = [{ name: 'imagePath', url }]
return false
},
export function getObjectURL(data) {
var url = null
if (window.createObjectURL !== undefined) {
url = window.createObjectURL(data)
} else if (window.webkitURL !== undefined) {
try {
url = window.webkitURL.createObjectURL(data)
} catch (error) {
console.log(error)
}
} else if (window.URL !== undefined) {
try {
url = window.URL.createObjectURL(data)
} catch (error) {
console.log(error)
}
}
return url
}
export function base64toFile(dataurl, filename = 'file') {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let suffix = mime.split('/')[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
}
上传formData类型的文件
感悟
以前的项目很少用到这个请求的类型,虽说学过,但是也没想起来。当上传图片的时候需要将请求头设置为multiparty/form-data 。然后我就按照常规的请求给数据了,结果就是后端报错。
解决
单独配置请求头为multiparty/form-data , 要new 一个formData 实例,使用formData.append() 添加字段,请求的时候将创建的formData做为请求体传入即可
代码
api文件
handelConfirm(data) {
return requestJson({
method: 'post',
url: 'app/manage/informationConfig',
data,
mock: false,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
页面文件
async handelConfirm() {
const { id, type, image, introduction } = this.dataForm
const formData = new FormData()
formData.append('image', image)
formData.append('id', id)
formData.append('type', type)
formData.append('introduction', introduction)
const { code, msg } = await http.handelConfirm(formData)
if (code === 0) {
this.$message.success('配置信息成功')
this.configDialogClosed()
console.log(this.$parent)
this.$nextTick(() => {
this.$parent.initData()
})
t
} else {
this.$message.error(msg)
}
}
-----------------------未完待续-----------------------------------
|