Vue 爬坑之旅 -- 在vue单页应用中利用 H5+ 实现扫码功能
最近做了个项目,项目本身没什么复杂的,就是其中有一个功能是要求调用手机摄像头扫描并识别二维码,最后还要打包成一个App。基于以上的需求,最后决定采用的技术方案是前端页面用 vue 来写,然后涉及到扫码和打原生App的话就用 HBuilder 的 wap2app 的方式,综合时间和开发成本上的考虑,这种方案是最合适的。前端界面没什么说的,这里要说的是在实现扫码功能和 App 打包的时候会碰到的坑..
最近做了个项目,项目本身没什么复杂的,就是其中有一个功能是要求调用手机摄像头扫描并识别二维码,最后还要打包成一个App。
基于以上的需求,最后决定采用的技术方案是前端页面用 vue 来写,然后涉及到扫码和打原生App的话就用 HBuilder 的 wap2app 的方式,综合时间和开发成本上的考虑,这种方案是最合适的。
前端界面没什么说的,这里要说的是在实现扫码功能和 App 打包的时候会碰到的坑,在这里记录一下,以避免再次踩坑。
vue 项目打包成 App
要实现扫码功能,需要先用 Hbuilder 生成一个 App 壳子出来,实际上这个壳子里面就是一个原生的 webview,我们的 vue 程序是通过 webview 加载的。所以这里先说 vue 程序打包成 App 时候要注意的地方。
选择合适的转换 App 的方式
实际上,HBuilder 将 web 程序转为 App 有两种方式:
- WapApp:这种方式是先将 vue 程序部署到自己的服务器上,分配一个访问地址,然后在 HBuilder 中填入该地址,点创建,HBuilder 会生成一个 App,这个 App 里面其实啥都没有,你打开创建的项目目录就只能看到几个配置文件。其实它的本质就是创建一个 App 的壳子,然后在里面创建一个 webview 来加载我们创建项目时输入的链接。
- 5+ App:这种方式其实跟上面那个本质上还是一样,唯一的区别是我们将 vue 打包后的所有文件放在生成的壳子 App 里面,就是少了服务器部署和 webview 从服务器上读取资源的过程,直接是加载的本地资源,这个的好处就是会比第一种方式加载速度上要快一些,但缺点也同样明显,就是程序更新跟纯原生的 App 更新一样需要先下载更新包安装后才能更新。
说完了区别我相信大部分人会选择第一种方式,没啥,就为了更新方便。
sitemap.json 文件的配置
用 Wap2App 方式打包的 App,里面有个 sitemap.js 文件,这个文件控制着 App 的一些基础功能,为了增强用户体验,需要对这个文件里面的配置项做一些修改。sitemap 文档
其实我做的优化就两个,
- 关掉退出 App 时候 toast 里面的反馈意见链接,这个反馈意见是反馈给 HBuilder 的,所以我么的用户并不需要看到这个,普通用户看见了反馈了也没用。。。
- 针对安卓的物理返回键做处理,安卓有物理返回键功能,按一下返回上一个页面,需要支持一下这个功能。
Talk is cheap,show you the code!
{
"global": {
......
"easyConfig": {
"quit": {
"toast": {
"showFeedback": false //不显示“反馈意见”链接,默认为true
}
}
}
},
"pages": [{
......
"easyConfig": {
"back": {
"history": true //允许执行history.back
}
}
}]
}
其实就是分别在 global 和 pages 节点下配置 easyConfig ,一个处理退出 App 时的提示,一个处理物理返回键。
扫码
上面说完了 App 打包的事情,现在有了 App 壳子,就可以依据该壳子提供的 H5+ runtime 来实现扫码功能了,它的工作原理就是封装了一系列的 api,利用 js 和原生通信的能力,调起原生的摄像头,扫描二维码并进行解析。原理很简单,但是要自己实现这一整套过程还是很复杂的,所以就直接把他们的拿过来用了。。。。
通常情况下,App 中的扫码功能就是通过点一个按钮,然后打开扫码页面,拿到了扫码结果后执行相应的操作并关掉扫码页面。所以我就单独准备了一个扫码的页面,App 中要用到扫码功能的时候先跳到这个页面,然后扫码并执行相应的逻辑。
<template>
<div class="scan">
<div id="bcid">
<div style="height:40%"></div>
<p class="tip">...载入中...</p>
</div>
</div>
</template>
<script>
/**
* h5+ 扫码功能实现
*/
let scan = null
export default {
name:'Scan',
data () {
return{
fromRouter:'',//进入扫码页面的上一个路由
}
},
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例,记录上一个页面的路由,
vm.fromRouter = from.fullPath
})
},
mounted() {
this.startRecognize();
},
beforeDestroy(){
this.closeScan();
},
methods: {
// 创建扫描控件
startRecognize() {
let that = this
if (!window.plus) return
scan = new plus.barcode.Barcode('bcid')
scan.onmarked = onmarked
that.startScan()
function onmarked(type, result, file) {
switch (type) {
case plus.barcode.QR:
type = 'QR'
break
case plus.barcode.EAN13:
type = 'EAN13'
break
case plus.barcode.EAN8:
type = 'EAN8'
break
default:
type = '其它' + type
break
}
// 获得code
result = result.replace(/\n/g, '')
if(result){
// alert(result)
// alert(that.fromRouter)
// 成功,关闭控件,带参数跳转到正常页面去
if (result.indexOf('merchantNo=') > -1) {
//如果扫码结果中包含有商户ID,就截取ID拼接到商户确权路由中并跳转
let merChantId = result.substr(result.lastIndexOf('=') + 1)
that.$router.replace(`/home/merchantConfirm/${merChantId}`);
}else if (result.indexOf('0x') === 0) {
// alert('address')
//如果扫码结果是钱包地址,则保存该地址并返回上一个页面
that.$store.commit('setWalletAddress',result)
// alert('setWalletAddress---' + that.$store.state.walletAddress)
that.$router.replace(that.fromRouter)
} else {
that.$router.replace(that.fromRouter)
}
}else{
// 失败,关闭控件,重新扫描
that.myUtils.showToast(that,'二维码识别失败,请重试');
that.$router.replace(that.fromRouter)
}
that.closeScan();
}
},
// 开始扫描
startScan() {
if (!window.plus) return
scan.start()
},
// 关闭扫描
cancelScan() {
if (!window.plus) return
scan.cancel()
},
// 关闭条码识别控件
closeScan() {
if (!window.plus) return
scan.close()
}
},
}
</script>
<style lang="less">
.scan {
height: 100%;
#bcid {
width: 100%;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
text-align: center;
color: #fff;
background: #ccc;
}
}
</style>
代码简单,而且也有注释,就不多 BB 了。这里还有一个小点要注意的就是,在进入和离开扫码页面的时候,要使用 replace 方法切换路由,不然在离开这个页面后会出现要按两下返回键才会返回的问题。
这里我不得不吐槽下各个互联网公司写文档的哥们,开发这么多年,接入了各种 SDK,看了各种文档,好像还没有哪个公司的文档能够让人一看就懂,照着文档做一次成功的,很多时候文档还不如别人写的博客管用,其实功能是好的,但特么的文档能不能写的用心点,能不能写的让人照着文档做能一次成功的。在文档这方面,国内公司跟国外公司真的差了不止一点半点。
更多推荐
所有评论(0)