一、首先下载需要的插件
npm install @zxing/library --save
二、假设场景:页面上有个按钮,点击触发扫码功能 @click='scanCode()',在 methods 写入该方法。
scanCode() { console.log('浏览器信息', navigator.userAgent); this.$router.push({ path: '/qrcode' }); }
三、在 vue-router 写入对应页面的路由。
{ title: '扫码页面', name: 'Qrcode', path: '/qrcode', component: () => import('@/views/qrcode.vue') }
四、扫码页面代码,通过与 video 标签结合使用,把以下代码直接全部拷贝到新建的一个 qrcode.vue 文件里使用
<template> <div class="page-scan"> <!--返回--> <van-nav-bar title="扫描二维码" :fixed="true" :placeholder="true" left-arrow @click-left="onClickLeft" /> <!-- 扫码区域 --> <video ref="video" id="video" class="scan-video" autoplay></video> <!-- 提示语 --> <div v-show="tipShow" class="scan-tip">{{ tipMsg }}</div> </div> </template> <script> import { BrowserMultiFormatReader } from "@zxing/library"; export default { name: "scanCodePage", data() { return { loadingShow: false, codeReader: null, scanText: "", vin: null, tipMsg: "正在尝试识别....", tipShow: false, }; }, created() { this.codeReader = new BrowserMultiFormatReader(); this.codeReader.reset(); this.openScan(); }, beforeDestroy() { document.getElementById("video").srcObject.getTracks()[0].stop(); }, watch: { $route(to, from) { if (to.path == "/scanCodePage") { this.codeReader = new BrowserMultiFormatReader(); this.openScanTwo(); } }, }, methods: { async openScan() { this.codeReader .getVideoInputDevices() .then((videoInputDevices) => { this.tipShow = true; this.tipMsg = "正在调用摄像头..."; // 默认获取第一个摄像头设备id let firstDeviceId = videoInputDevices[0].deviceId; // 获取第一个摄像头设备的名称 const videoInputDeviceslablestr = JSON.stringify( videoInputDevices[0].label ); if (videoInputDevices.length > 1) { // 判断是否后置摄像头 if (videoInputDeviceslablestr.indexOf("back") > -1) { firstDeviceId = videoInputDevices[0].deviceId; } else { firstDeviceId = videoInputDevices[1].deviceId; } } this.decodeFromInputVideoFunc(firstDeviceId); }) .catch((err) => { this.tipShow = false; console.error(err); }); }, async openScanTwo() { this.codeReader = await new BrowserMultiFormatReader(); this.codeReader .getVideoInputDevices() .then((videoInputDevices) => { this.tipShow = true; this.tipMsg = "正在调用摄像头..."; // 默认获取第一个摄像头设备id let firstDeviceId = videoInputDevices[0].deviceId; // 获取第一个摄像头设备的名称 const videoInputDeviceslablestr = JSON.stringify( videoInputDevices[0].label ); if (videoInputDevices.length > 1) { // 判断是否后置摄像头 if (videoInputDeviceslablestr.indexOf("back") > -1) { firstDeviceId = videoInputDevices[0].deviceId; } else { firstDeviceId = videoInputDevices[1].deviceId; } } this.decodeFromInputVideoFunc(firstDeviceId); }) .catch((err) => { this.tipShow = false; console.error(err); }); }, decodeFromInputVideoFunc(firstDeviceId) { this.codeReader.reset(); // 重置 this.scanText = ""; this.codeReader.decodeFromInputVideoDeviceContinuously( firstDeviceId, "video", (result, err) => { this.tipMsg = "正在尝试识别..."; this.scanText = ""; if (result) { //这里是扫码后的结果,具体怎么用要看项目需求 } if (err && !err) { this.tipMsg = "识别失败"; setTimeout(() => { this.tipShow = false; }, 2000); console.error(err); } } ); }, onClickLeft() { document.getElementById("video").srcObject.getTracks()[0].stop(); setTimeout(() => { this.$router.back(); }, 200); }, }, }; </script> <style lang="less" scoped> /deep/.van-nav-bar__title { font-size: 18px; font-weight: 800; } /deep/ .van-nav-bar .van-icon { color: #333; font-size: 24px; } .scan-video { height: 80vh; width: 100%; } .scan-tip { text-align: center; margin-bottom: 10vh; color: white; font-size: 5vw; } .page-scan { overflow-y: hidden; background-color: #363636; } </style>