Vue圖片裁剪功能實(shí)現(xiàn)代碼
一、效果展示:
1、表單的圖片上傳項(xiàng):
- 新增時(shí)默認(rèn)一個(gè)空白Input框
- 更新時(shí)展示以往上傳存放的圖片,
- 點(diǎn)擊【查看】瀏覽完整大小
- 點(diǎn)擊【刪除】清空src地址,重新上傳新照片



2、裁剪框頁(yè)面
- 先選擇裁剪的圖片
- 右側(cè)展示裁剪區(qū)域
- 支持放大縮小,圖片旋轉(zhuǎn)
- 點(diǎn)擊【上傳圖片】調(diào)用后臺(tái)上傳接口進(jìn)行上傳


二、代碼部分
1、首先安裝Vue-Cropper,基于此組件的基礎(chǔ)上開發(fā)的裁剪頁(yè)面
npm install vue-cropper "vue-cropper": "^0.5.8"
2、裁剪彈窗的組件編寫:
<template>
<div
v-loading="loading"
class="cropper-content"
>
<div class="cropper-box">
<div class="cropper">
<vue-cropper
ref="cropper"
:img="option.img"
:output-size="option.outputSize"
:output-type="option.outputType"
:info="option.info"
:can-scale="option.canScale"
:auto-crop="option.autoCrop"
:auto-crop-width="autoCropWidth"
:auto-crop-height="autoCropHeight"
:fixed="option.fixed"
:fixed-number="option.fixedNumber"
:full="option.full"
:fixed-box="option.fixedBox"
:can-move="option.canMove"
:can-move-box="option.canMoveBox"
:original="option.original"
:center-box="option.centerBox"
:height="option.height"
:info-true="option.infoTrue"
:max-img-size="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
@imgLoad="imgLoad"
/>
</div>
<!--底部操作工具按鈕-->
<div class="footer-btn">
<div class="scope-btn">
<label
class="btn"
for="uploads"
>選擇圖片</label>
<input
id="uploads"
type="file"
style="position:absolute; clip:rect(0 0 0 0);"
accept="image/png, image/jpeg, image/gif, image/jpg"
@change="selectImg($event)"
>
<el-button
size="mini"
type="danger"
plain
icon="el-icon-zoom-in"
@click="changeScale(1)"
>放大</el-button>
<el-button
size="mini"
type="danger"
plain
icon="el-icon-zoom-out"
@click="changeScale(-1)"
>縮小</el-button>
<el-button
size="mini"
type="danger"
plain
@click="rotateLeft"
>? 左旋轉(zhuǎn)</el-button>
<el-button
size="mini"
type="danger"
plain
@click="rotateRight"
>? 右旋轉(zhuǎn)</el-button>
</div>
<div class="upload-btn">
<el-button
size="mini"
type="success"
@click="uploadImg('blob')"
>上傳圖片<i class="el-icon-upload" /></el-button>
</div>
</div>
</div>
<!--預(yù)覽效果圖-->
<div class="show-preview">
<div
:style="previews.div"
class="preview"
>
<img
:src="previews.url"
:style="previews.img"
>
</div>
</div>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
import { uploadFile } from '@/api/smrz/setting'
import { regularFileName } from '@/utils'
export default {
name: 'CropperImage',
components: {
VueCropper
},
/* props: ['name2'],*/
props: {
autoCropWidth: { // 默認(rèn)生成截圖框?qū)挾?
type: Number,
default: 410
},
autoCropHeight: { // 默認(rèn)生成截圖框高度
type: Number,
default: 150
},
busType: {
type: String,
default: 'advertPic'
}
},
data() {
return {
loading: false,
name: this.Name,
previews: {},
option: {
img: '', // 裁剪圖片的地址
outputSize: 1, // 裁剪生成圖片的質(zhì)量(可選0.1 - 1)
outputType: 'jpeg', // 裁剪生成圖片的格式(jpeg || png || webp)
info: true, // 圖片大小信息
canScale: true, // 圖片是否允許滾輪縮放
autoCrop: true, // 是否默認(rèn)生成截圖框
// autoCropWidth: 410, 默認(rèn)生成截圖框?qū)挾?
// autoCropHeight: 150, 默認(rèn)生成截圖框高度
fixed: false, // 是否開啟截圖框?qū)捀吖潭ū壤?
fixedNumber: [1.53, 1], // 截圖框的寬高比例
full: true, // false按原比例裁切圖片,不失真
fixedBox: true, // 固定截圖框大小,不允許改變
canMove: true, // 上傳圖片是否可以移動(dòng)
canMoveBox: true, // 截圖框能否拖動(dòng)
original: true, // 上傳圖片按照原始比例渲染
centerBox: false, // 截圖框是否被限制在圖片里面
height: true, // 是否按照設(shè)備的dpr 輸出等比例圖片
infoTrue: false, // true為展示真實(shí)輸出圖片寬高,false展示看到的截圖框?qū)捀?
maxImgSize: 3000, // 限制圖片最大寬度和高度
enlarge: 1, // 圖片根據(jù)截圖框輸出比例倍數(shù)
mode: '230px 150px' // 圖片默認(rèn)渲染方式
},
randomFileName: ''
}
},
methods: {
// 初始化函數(shù)
imgLoad(msg) {
console.log('工具初始化函數(shù)=====' + msg)
},
// 圖片縮放
changeScale(num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
// 向左旋轉(zhuǎn)
rotateLeft() {
this.$refs.cropper.rotateLeft()
},
// 向右旋轉(zhuǎn)
rotateRight() {
this.$refs.cropper.rotateRight()
},
// 實(shí)時(shí)預(yù)覽函數(shù)
realTime(data) {
this.previews = data
},
// 選擇圖片
selectImg(e) {
const file = e.target.files[0]
if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
this.$message({
message: '圖片類型要求:jpeg、jpg、png',
type: 'error'
})
return false
}
// 轉(zhuǎn)化為blob
const reader = new FileReader()
reader.onload = (e) => {
let data
if (typeof e.target.result === 'object') {
data = window.URL.createObjectURL(new Blob([e.target.result]))
} else {
data = e.target.result
}
this.option.img = data
}
console.log(`file.name => ${file.name}`)
// 轉(zhuǎn)化為base64
reader.readAsDataURL(file)
},
// 上傳圖片
uploadImg(type) {
const _this = this
if (type === 'blob') {
// 獲取截圖的blob數(shù)據(jù)
this.$refs.cropper.getCropBlob(async(data) => {
_this.loading = true
const formData = new FormData()
// formData.append('file', data, this.createNewFileName())
// if (this.autoCropWidth === 100) {
// formData.append('subDir', 'exchange')
// } else if (this.autoCropHeight === 80) {
// formData.append('subDir', 'task')
// } else {
// formData.append('subDir', 'rotate')
// }
_this.randomFileName = this.createNewFileName()
// 給blob對(duì)象的filename屬性賦值文件名
formData.append('rpc', data, _this.randomFileName)
// 給參數(shù)賦值文件名
formData.append('fileName', _this.randomFileName)
formData.append('busType', _this.busType)
/* this.fileName = data.file.name
formData.append('fileName', this.fileName)*/
// 調(diào)用axios上傳
/* const { data: res } = await _this.$http.post('/api/file/imgUpload', formData)*/
uploadFile(formData).then(res => {
/* this.handleSuccess(res)*/
if (res.code === 200) {
_this.$message({
message: '圖片上傳成功',
type: 'success'
})
// const data = res.data.replace('[', '').replace(']', '').split(',')
// const imgInfo = {
// name: 'DX.jpg',
// url: res.data.agentUrl,
// storeUrl: res.data.storeUrl,
// uploadResult: res.data.uploadResult
// }
// _this.$emit('uploadImgSuccess', imgInfo)
// 添加隨機(jī)生成的文件名
res.fileName = _this.randomFileName
_this.$emit('uploadImgSuccess', res)
} else {
_this.$message({
message: '文件服務(wù)異常,請(qǐng)聯(lián)系管理員!',
type: 'error'
})
}
}).finally(() => {
_this.loading = false
})
})
/* if (flag) {
this.$message.warning('請(qǐng)選擇圖片')
}*/
}
},
createNewFileName() {
// const now = Date.now()
// const fileName = now + '-' + Math.ceil(Math.random() * 100)
// return fileName + '.jpg'
const fileName = regularFileName()
return fileName + '.jpg'
}
}
}
</script>
<style scoped lang="scss">
.cropper-content {
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.cropper-box {
flex: 1;
width: 100%;
.cropper {
width: auto;
height: 300px;
}
}
.show-preview {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
.preview {
overflow: hidden;
border: 1px solid #67c23a;
background: #cccccc;
}
}
}
.footer-btn {
margin-top: 30px;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.scope-btn {
display: flex;
display: -webkit-flex;
justify-content: space-between;
padding-right: 10px;
}
.upload-btn {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
}
.btn {
outline: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
-webkit-transition: 0.1s;
transition: 0.1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409eff;
border-color: #409eff;
margin-right: 10px;
}
}
</style>需要更改成自己的上傳接口:
import { uploadFile } from '@/api/smrz/setting'后臺(tái)接口參數(shù)如下,要求表單方式上傳
/**
* 上傳附件
*
* @param file 文件流(注意帶文件后綴,統(tǒng)一使用.jpg結(jié)尾)
* @param fileName 文件名稱(唯一性)
* @param busType 業(yè)務(wù)類型(具體值參考ApiConstants類中FILE_開頭常量說(shuō)明)
* @author wangkun
* @createTime 2022/7/19 17:18
*/
@PostMapping(value = "/file/upload", consumes = "multipart/form-data")
public RpcResult uploadFile(@RequestParam(value = "rpc") MultipartFile file, @RequestParam(value = "fileName") String fileName, @RequestParam(value = "busType") String busType) {在uploadImg函數(shù)這里,使用FormData對(duì)象包裝請(qǐng)求參數(shù)
注意append方法,要給文件對(duì)象指定文件名,必須要入?yún)⒌谌齻€(gè)參數(shù)
否則默認(rèn)名稱blob

按實(shí)際接口對(duì)應(yīng)調(diào)整參數(shù)即可
const formData = new FormData()
_this.randomFileName = this.createNewFileName()
// 給blob對(duì)象的filename屬性賦值文件名
formData.append('rpc', data, _this.randomFileName)
// 給參數(shù)賦值文件名
formData.append('fileName', _this.randomFileName)
formData.append('busType', _this.busType)
uploadFile(formData)其它自定義參數(shù),通過(guò)Props屬性傳入此組件
props: {
autoCropWidth: { // 默認(rèn)生成截圖框?qū)挾?
type: Number,
default: 410
},
autoCropHeight: { // 默認(rèn)生成截圖框高度
type: Number,
default: 150
},
busType: {
type: String,
default: 'advertPic'
}
},文件名的生成方法,就是當(dāng)前時(shí)間按單位數(shù)值排序
實(shí)際使用根據(jù)業(yè)務(wù)實(shí)際情況改寫
export function regularFileName() {
const now = new Date()
const year = now.getFullYear()
const month = digitFix(now.getMonth() + 1)
const dayOfMonth = digitFix(now.getDate())
const hour = digitFix(now.getHours())
const minute = digitFix(now.getMinutes())
const second = digitFix(now.getSeconds())
const millSecond = now.getMilliseconds()
return `${year}${month}${dayOfMonth}${hour}${minute}${second}${millSecond}`
}const fileName = `${regularFileName()}3、【圖片上傳表單項(xiàng)】組件編寫
<template>
<div class="cropper-app">
<el-form
ref="ruleForm"
:model="formValidate"
:rules="ruleValidate"
label-width="110px"
class="demo-ruleForm"
>
<el-form-item
:label="label"
prop="mainImage"
>
<div class="list-img-box">
<div
v-if="formValidate.mainImage !== ''"
class="img_div"
style="height: 100px;"
>
<img
:src="formValidate.mainImage"
alt="圖片找不到"
>
<a href="#" rel="external nofollow" >
<div class="mask">
<h3 style="">
<i
class="el-icon-zoom-in"
@click="clickImg('zoom-in')"
/>
<i
class="el-icon-delete"
@click="clickImg('delete')"
/>
</h3>
</div>
</a>
</div>
<div
v-else
class="upload-btn"
style="height: 100px;width: 200px"
@click="uploadPicture('flagImg')"
>
<i
class="el-icon-plus"
style="font-size: 30px;"
/>
<!--<span>封面設(shè)置</span>-->
</div>
</div>
<input
v-model="formValidate.mainImage"
type="hidden"
placeholder="請(qǐng)?zhí)砑臃饷?
>
</el-form-item>
</el-form>
<!-- 剪裁組件彈窗 -->
<el-dialog
v-if="cropperModel"
title="圖片剪切"
:visible.sync="cropperModel"
width="1020px"
center
append-to-body
>
<cropper-image
v-if="cropperModel"
ref="child"
:auto-crop-width="autoCropWidth"
:auto-crop-height="autoCropHeight"
:bus-type="busType"
@uploadImgSuccess="handleUploadSuccess"
/>
</el-dialog>
<!--查看大封面-->
<el-dialog
title=""
:visible.sync="imgVisible"
center
append-to-body
>
<img
v-if="imgVisible"
:src="imgUrl"
style="width: 100%"
alt="查看"
>
</el-dialog>
</div>
</template>
<script>
import CropperImage from '@/components/CropperImage'
import { commonsDownloadAPI } from '@/api/smrz/setting'
export default {
name: 'Tailoring',
components: { CropperImage },
props: {
label: {
type: String,
default: '上傳圖片'
},
url: {
type: String
},
autoCropWidth: { // 默認(rèn)生成截圖框?qū)挾?
type: Number,
default: 410
},
autoCropHeight: { // 默認(rèn)生成截圖框高度
type: Number,
default: 150
},
isSignFlag: {
type: Boolean,
default: false
},
busType: {
type: String,
default: 'busType'
}
},
data() {
var imageUrl2 = (rule, value, callback) => {
if (!this.isSignFlag) {
return callback()
}
if (!value) {
return callback(new Error('請(qǐng)輸上傳圖片'))
}
return callback()
}
return {
formValidate: {
mainImage: ''
},
ruleValidate: {
mainImage: [
/* { required: true, message: '請(qǐng)上傳圖片', trigger: 'blur' }*/
{ required: true, validator: imageUrl2, trigger: 'blur' }
]
},
// 裁切圖片參數(shù)
cropperModel: false,
cropperName: '',
imgUrl: '',
imgVisible: false,
dialogImageUrl: '',
dialogVisible: false
}
},
created() {
this.formValidate.mainImage = this.url
this.imgUrl = this.url
},
methods: {
validateForm() {
this.$refs['ruleForm'].validate((valid) => {
this.$emit('validVal', valid)
})
},
// 封面設(shè)置
uploadPicture(name) {
this.cropperName = name
this.cropperModel = true
},
// 圖片上傳成功后
async handleUploadSuccess(data) {
// this.formValidate.mainImage = data.url
// 圖片回顯
const { data: res2, code } = await commonsDownloadAPI({
fileName: data.fileName,
busType: 'advertPic'
})
const imgBase64 =
code !== 200
? '-1' : `data:image/jpeg;base64,${res2.data}`
this.formValidate.mainImage = imgBase64
/* switch (data.name) {
case 'flagImg':
this.formValidate.mainImage = data.url
console.log('最終輸出' + data.name)
console.log('最終輸出2' + this.formValidate)
break
}*/
this.cropperModel = false
this.$emit('uploadSuccess', data)
},
clickImg(val) {
if (val === 'delete') {
this.formValidate.mainImage = ''
this.$emit('deleteImage')
} else if (val === 'zoom-in') {
//
this.imgUrl = this.formValidate.mainImage
this.imgVisible = true
}
}
}
}
</script>
<style scoped>
.upload-list-cover {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 40px;
align-items: center;
background: rgba(0, 0, 0, 0.6);
opacity: 0;
transition: opacity 1s;
}
.cover_icon {
font-size: 30px;
}
.upload-btn {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border: 1px solid #cccccc;
border-radius: 5px;
overflow: hidden;
box-shadow: 0 0 1px #cccccc;
}
.upload-btn:hover {
border: 1px solid #69b7ed;
}
.upload-btn i {
margin: 5px;
}
.img_div img {
width: 200px !important;
height: 100px !important;
/* margin: 20px 400px 0 400px;
position: relative;
width: 531px;
height: 354px;*/
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 100px;
background: rgba(101, 101, 101, 0.6);
color: #ffffff;
opacity: 0;
}
.mask h3 {
text-align: center;
line-height: 60px;
}
.img_div a:hover .mask {
opacity: 0.8;
}
</style>表單項(xiàng)組件需要引入
1、裁剪組件
2、圖片下載接口
import CropperImage from '@/components/CropperImage'
import { commonsDownloadAPI } from '@/api/smrz/setting'3、表單項(xiàng)設(shè)置了自定義校驗(yàn)
var imageUrl2 = (rule, value, callback) => {
if (!this.isSignFlag) {
return callback()
}
if (!value) {
return callback(new Error('請(qǐng)輸上傳圖片'))
}
return callback()
}就是檢查src有沒(méi)有地址或者base64資源,校驗(yàn)觸發(fā)的效果:

4、圖片上傳后的回調(diào)處理:
上傳成功后,回到表單頁(yè)需要立即回顯之前上傳的圖片
所以需要調(diào)用圖片下載接口來(lái)獲取剛剛上傳的資源,
在這個(gè)回調(diào)方法中實(shí)現(xiàn),因?yàn)橄螺d接口提供的資源不是圖片地址,而是返回Base64編碼
這里我寫的是base64編碼資源的回顯處理
實(shí)際使用根據(jù)業(yè)務(wù)實(shí)際情況改寫
// 圖片上傳成功后
async handleUploadSuccess(data) {
// this.formValidate.mainImage = data.url
// 圖片回顯
const { data: res2, code } = await commonsDownloadAPI({
fileName: data.fileName,
busType: 'advertPic'
})
const imgBase64 =
code !== 200
? '-1' : `data:image/jpeg;base64,${res2.data}`
this.formValidate.mainImage = imgBase64
/* switch (data.name) {
case 'flagImg':
this.formValidate.mainImage = data.url
console.log('最終輸出' + data.name)
console.log('最終輸出2' + this.formValidate)
break
}*/
this.cropperModel = false
this.$emit('uploadSuccess', data)
},4、業(yè)務(wù)功能引用
引入表單項(xiàng)
import Tailoring from '@/components/Tailoring'
聲明組件,并注入?yún)?shù)
<div class="ant-upload-preview">
<tailoring
v-if="true"
ref="child"
label="廣告圖片"
:is-sign-flag="true"
:url="url"
:bus-type="businessType"
:auto-crop-height="80"
:auto-crop-width="410"
@uploadSuccess="uploadSuccess"
@validVal="validVal"
/>
</div>- url是一開始加載組件需要回顯的圖片資源地址
- isSignFlag變量用來(lái)輔助自定義校驗(yàn)的,為false時(shí)直接放行校驗(yàn),所以默認(rèn)寫死true
- bus-type是自定義的業(yè)務(wù)參數(shù)
- auto-crop的寬高用來(lái)配置裁剪的寬高,預(yù)覽大小和裁剪大小合并使用這兩個(gè)參數(shù)
上傳成功的回調(diào),uploadSuccess,可以在組件自定義需要的參數(shù)
這里是以圖片名稱作為記錄主鍵,所以要傳入這個(gè)文件名
實(shí)際使用根據(jù)業(yè)務(wù)實(shí)際情況改寫
async uploadSuccess(res) {
console.log(`上傳結(jié)果 res -> ${JSON.stringify(res)}`)
const fileName = res.fileName
this.newId = fileName.substring(0, fileName.lastIndexOf('.'))
},校驗(yàn)值,應(yīng)該是返回校驗(yàn)后的src值,但我這里沒(méi)用上,所以不執(zhí)行任何邏輯
validVal(val) {},
要觸發(fā)【裁剪表單項(xiàng)】校驗(yàn),使用
this.$refs.child.validateForm()
到此這篇關(guān)于Vue圖片裁剪功能支持的文章就介紹到這了,更多相關(guān)vue圖片裁剪內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
electron-vue利用webpack打包實(shí)現(xiàn)多頁(yè)面的入口文件問(wèn)題
項(xiàng)目需要在electron的項(xiàng)目中新打開一個(gè)窗口,利用webpack作為靜態(tài)資源打包器,發(fā)現(xiàn)在webpack中可以設(shè)置多頁(yè)面的入口,今天來(lái)講一下我在electron中利用webpack建立多頁(yè)面入口的踩坑經(jīng)驗(yàn),需要的朋友可以參考下2019-05-05
基于Vue中點(diǎn)擊組件外關(guān)閉組件的實(shí)現(xiàn)方法
下面小編就為大家分享一篇基于Vue中點(diǎn)擊組件外關(guān)閉組件的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
vue 使用 sortable 實(shí)現(xiàn) el-table 拖拽排序功能
這篇文章主要介紹了vue 使用 sortable 實(shí)現(xiàn) el-table 拖拽排序功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
vue+element 模態(tài)框表格形式的可編輯表單實(shí)現(xiàn)
這篇文章主要介紹了vue+element 模態(tài)框表格形式的可編輯表單實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
elementui的table列超出隱藏tooltip懸浮顯示問(wèn)題
這篇文章主要介紹了elementui的table列超出隱藏tooltip懸浮顯示問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Vue前端導(dǎo)出Excel文件的詳細(xì)實(shí)現(xiàn)方案
在開發(fā)后臺(tái)管理系統(tǒng)的時(shí)候,很多地方都要用到導(dǎo)出excel表格,比如將table中的數(shù)據(jù)導(dǎo)出到本地,下面這篇文章主要給大家介紹了關(guān)于Vue導(dǎo)出Excel文件的相關(guān)資料,需要的朋友可以參考下2021-09-09
Vue?關(guān)于$emit與props的使用示例代碼
父組件使用 props 把數(shù)據(jù)傳給子組件,子組件使用 $emit 觸發(fā)父組件的自定義事件,今天通過(guò)示例給大家詳細(xì)介紹下Vue?關(guān)于$emit與props的使用,感興趣的朋友一起看看吧2022-03-03
vue使用axios時(shí)關(guān)于this的指向問(wèn)題詳解
最近在學(xué)習(xí)使用vue+axios,在使用中發(fā)現(xiàn)了一個(gè)問(wèn)題,下面總結(jié)分享給大家,這篇文章主要給大家介紹了關(guān)于vue使用axios時(shí)this的指向問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12

