实现效果

请添加图片描述

实现代码

1.给img添加属性

<div class="in_code">
   <img
       :src="verificationImg"
        @click="acquireVerification"
   />
</div>

src

src与js中定义的属性双向绑定,图片属性的来源

:src="verificationImg"

@click

实现点击图片换一张验证码

@click="acquireVerification"

2.在进入需要验证码页面查询

因为我这里是通过对话框实现的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VUK1D7cd-1646028123555)(assets/验证码图片-20220227085640-z6s71j1.jpg)]

所以,在对话框打开的时候调用了 获取验证码的接口

openDiag(val, val2) {
      this.dialogVisible = val
      this.activeName = val2
      this.acquireVerification() // 就是这个接口
},

3.点击图片,获取验证码

async acquireVerification(){
    const data = await api.verificationCode.verificationCode();
}

接口返回的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YppW9EYA-1646028123555)(assets/接口返回的数据-20220227085707-jbe1zuq.jpg)]

{
  "code": 200,
  "message": "验证码",
  "data": {
    "image": "data:image/png;base64,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",
    "vCode": 1645923302817
  }
}

4.获取时间戳并保存

this.vCode = data.data.vCode.toString();

通过时间戳转换,我获取到了当前时间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GWz1mRBy-1646028123556)(assets/image-20220227085759-9hb7sxw.png)]

因为此时用户还没有登录,所以对于后端来说,不知道该用户是谁。所以只能给一个临时的身份认证。即给一个毫秒级的时间戳

此时在后端,每次点击图片获取到验证码的时候,都已经构建了一个key-value键值对,每一个时间戳对应一个验证码,对应一个人

5.获取image

image:是图像

网络中,会通过base64编码,以字符串形式发送图片。所以现在我们需要解码

data:image/png;base64,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

这一串为Data URL scheme语法

Base64 - MDN Web Docs Glossary: Definitions of Web-related terms | MDN (mozilla.org)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K18E6abD-1646028123556)(assets/image-20220227090737-55kr0in.png)]

data:文件类型,数据

现在我们将base64格式的图片转换为文件

  • 以逗号分割
let arr = dataUrl.split(',')

即可获得逗号前面的编码类型和编码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkC5NAYe-1646028123556)(assets/以逗号分隔-20220227090410-0newl29.jpg)]

  • 通过正则的惰性匹配获取内容

尽可能少的匹配字符

let type = arr[0].match(/:.*?);/)[1]

这里的意思就是从:;尽可能少的匹配字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xiU4yR5a-1646028123557)(assets/正则惰性匹配-20220227091908-4xia2z9.jpg)]

  • 通过/获取后缀
let suffix = type.split('/')[1]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7zLUkWXT-1646028123557)(assets/获取后缀-20220227091918-goe6hb4.jpg)]

  • 通过atob转换解码base64文件

Base64的编码与解码 - 术语表 | MDN (mozilla.org)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpSYBURI-1646028123557)(assets/image-20220227092052-y3nu0if.png)]

let decodeBase64 = atob(arr[1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r2obaE9b-1646028123557)(assets/atob解码base64-20220227092154-slryz3n.jpg)]

类型为string

  • 获取长度后,循环赋值到8位无符号整数数组内

每一个base64字符都代表6bit。因此,4个base64字符可以转换成3个字节(即占数组3位)

Uint8Array - JavaScript | MDN (mozilla.org)

创建之后,获取解码后的每一位unicode值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vaqEd5y7-1646028123558)(assets/image-20220227093643-2jrx0y7.png)]

let n = decodeBase64 .length
let u8Arr = new Unit8Array(n);
while(n --){
    u8Arr = decodeBase64.charCodeAt(n)
}
  • 返回一个file对象

File - Web API 接口参考 | MDN (mozilla.org)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6w4BmRId-1646028123558)(assets/image-20220227101117-wwzw7x3.png)]

return new File([u8Arr] , `${fileNmae}.${suffix}`,{
	type: type
})

base64转换成文件-完整代码

base64ImgtoFile(dataurl, filename = 'file') {
      debugger
      let arr = dataurl.split(',')
      let type = arr[0].match(/:(.*?);/)[1]
      let suffix = mime.split('/')[1]

      let decodeBase64 = atob(arr[1])
      let n = bstr.length
      let u8Arr = new Uint8Array(n)
      while (n--) {
        u8Arr[n] = decodeBase64.charCodeAt(n)
      }
      return new File([u8Arr], `${filename}.${suffix}`, {
        type: type,
      })
    },

6.获取imageURL

  • 创建一个blob

blob在MDN中的定义是一个不可变、原始数据的类文件对象。它的数据可以按照文本或二进制格式进行兑取,也可以转换成ReadableStream来用来数据操作

Blob - Web API 接口参考 | MDN (mozilla.org)

现在我们创建一个Blob对象,利用Blob()构造函数

let blob = new Blob([imgFile], { type:  'image/png'})
  • 获取到图片的src地址
let imageUrl = (window.URL || window.wekitURL).createObjectURL(blob)
  • 再赋值即可
this.verificationImg = imageUrl

完整代码

<div class="in_code">
    <img :src="verificationImg" @click="acquireVerification" />
</div>

……

export default {
  data() {
	verificationImg: '',
   }

async acquireVerification() {
      const data = await api.verificationCode.verificationCode()
      this.vCode = data.data.vCode.toString()
      let base64Img = data.data.image
      var imgFile = this.base64ImgtoFile(base64Img)
      // this.verificationImg = imgFile
      let blob = new Blob([imgFile], { type: 'image/png' })
      let imageUrl = (window.URL || window.webkitURL).createObjectURL(blob)
      this.verificationImg = imageUrl
    },

base64ImgtoFile(dataurl, filename = 'file') {
      debugger
      let arr = dataurl.split(',')
      let type = arr[0].match(/:(.*?);/)[1]
      let suffix = mime.split('/')[1]

      let decodeBase64 = atob(arr[1])
      let n = bstr.length
      let u8Arr = new Uint8Array(n)
      while (n--) {
        u8Arr[n] = decodeBase64.charCodeAt(n)
      }
      return new File([u8Arr], `${filename}.${suffix}`, {
        type: type,
      })
    },

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐