- 小程序webview组件,小程序和webview交互,小程序内联h5页面,小程序webview内网页实现微信支付
小程序支持webview以后,我们开发的好多h5页面,就可以直接在小程序里使用了,比如我们开发的微信商城,文章详情页,商品详情页,就可以开发一套,多处使用了。我们今天来讲一讲。在小程序的webview里实现微信支付功能。因为微信不允许在小程序的webview里直接调起微信支付。所以我们这节课就要涉及到小程序和webview的交互了。 老规矩先看效果。 因为这里涉及的东西比较多,录gif太多,没法上传,我就录制了一段视频出来。 https://v.qq.com/x/page/t0913iprnay.html 原理 先说下实现原理吧,实现原理就是我们在webview的h5页面里实现下单功能,然后点击支付按钮,我们点击支付按钮的时候会跳转到小程序页面,把订单号,订单总金额,传递到小程序里,然后小程序里使用订单号和订单金额去调起微信支付,实现付款,付款成功或者失败时都会有回调。我们再把对应的回调传递给webview,刷新webview里的订单和支付状态。 一,定义webview显示h5页面 关于webview的使用,我就不做讲解了,官方文档里写的很清楚,用起来也很简单。https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html [图片] webview很简单,就是用一个webview组件,显示我们的网页。 二,定义h5页面 我这里启动一个本地服务器,用来展示一个简单的h5页面。 [图片] 上图是我在浏览器里显示的效果。 接下来我们在小程序的webview里显示这个页面,也很简单,只需要把我们的src定义为我们的本地网页链接就可以了。 [图片] 这里有一点需要注意 因为我们是本地链接,我们需要到开发者工具里把这一项给勾选。 [图片] 三,来看下h5页面代码 [代码]<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>小程序内嵌webview</title> <style> .btn { font-size: 70px; color: red; } </style> </head> <body> <h1>我是webview里的h5页面</h1> <a id="desc" class="btn" onclick="jumpPay()">点击支付</a> <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script> <script> console.log(location.href); let payOk = getQueryVariable("payOk"); console.log("payOk", payOk) if(payOk){//支付成功 document.getElementById('desc').innerText="支持成功" document.getElementById('desc').style.color="green" }else{ document.getElementById('desc').innerText="点击支付" } //获取url里携带的参数 function getQueryVariable(variable) { var query = window.location.search.substring(1); var vars = query.split("&"); for (var i = 0; i < vars.length; i++) { var pair = vars[i].split("="); if (pair[0] == variable) { return pair[1]; } } return (false); } function jumpPay() { let orderId = Date.now();//这里用当前时间戳做订单号(后面使用你自己真实的订单号) let money = 1;//订单总金额(单位分) let payData = {orderId: orderId, money: money}; let payDataStr = JSON.stringify(payData);//因为要吧参数传递给小程序,所以这里需要转为字符串 const url = `../wePay/wePay?payDataStr=${payDataStr}`; wx.miniProgram.navigateTo({ url: url }); // console.log("点击了去支付", url) console.log("点击了去支付") } </script> </body> </html> [代码] h5代码这里不做具体讲解,只简单说下。我们就是在点击支付按钮时,用当前时间戳做为订单号(因为订单号要保证唯一),然后传一个订单金额(单位分),这里节约起见,就传1分钱吧,花的是自己的钱,心疼。。。。 关键点说一下 1, 必须引入jweixin,才可以实现h5跳转小程序。 <script type=“text/javascript” src=“https://res.wx.qq.com/open/js/jweixin-1.3.2.js”></script> 2,跳转到小程序页面的方法 [代码]const url = `../wePay/wePay?payDataStr=${payDataStr}`; wx.miniProgram.navigateTo({ url: url }); [代码] 这里要和你小程序的页面保持一致。payDataStr是我们携带的参数 [图片] 四,小程序支付页 来看下我们的小程序支付页 [图片] 小程序支付页功能很简单,就是来接收我们h5传过订单号和订单金额。然后去调起微信支付,实现支付。支付成功和支付失败都有对应的回调。 [图片] 支付我们这里实用的小程序云开发来实现的支付,核心代码只有10行。由于支付不是本节的重点,所以这里不做具体讲解。感兴趣的同学可以去看我写的文章和我录的视频 小程序支付文章:https://www.jianshu.com/p/2b391df055a9 小程序支付视频:https://edu.csdn.net/course/play/25701/310742 下面把小程序接收参数和支付的完整代码贴出来给大家 [代码]Page({ //h5传过来的参数 onLoad: function(options) { console.log("webview传过来的参数", options) //字符串转对象 let payData = JSON.parse(options.payDataStr) console.log("orderId", payData.orderId) let that = this; wx.cloud.callFunction({ name: "pay", data: { orderId: payData.orderId, money: payData.money }, success(res) { console.log("获取成功", res) that.goPay(res.result); }, fail(err) { console.log("获取失败", err) } }) }, //微信支付 goPay(payData) { wx.requestPayment({ timeStamp: payData.timeStamp, nonceStr: payData.nonceStr, package: payData.package, signType: 'MD5', paySign: payData.paySign, success(res) { console.log("支付成功", res) //你可以在这里支付成功以后,再跳会webview页,并把支付成功状态传回去 wx.navigateTo({ url: '../webview/webview?payOk=true', }) }, fail(res) { console.log("支付失败", res) } }) } }) [代码] 代码里注释很清楚,这里有一点,就是我们支付成功后,需要告诉h5我们支付成功了,通知h5去刷新订单或者支付状态。 到这里我们就完整的实现了小程序webview展示h5页面,并且做到了h5和小程序的交互,实现了小程序webview的支付功能。 是不是很简单呢。 源码地址 1,关注“编程小石头”公号,回复“webview”即可获取源码 2,也可以到我github下载源码 https://github.com/qiushi123/xiaochengxu_demos [图片]
2019-08-15 - 高阶性能渲染-wxs
我们永远没有资格说放弃,因为这是属于我们的年华,应该开出耀眼的繁花。 这里主要讲解两点使用方式 wxs --> 数据处理使用 wxs --> 拖拽使用 wxs介绍 1.先看看官方如何介绍的 ,如下 点我可以查看更多官方文档地址 WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。 WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。 WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。 WXS 函数不能作为组件的事件回调。 由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。 总的来说,我主要看中它快和方便 (有种在wxml写函数的感觉),并且处理函数内容后渲染不需要去调用setData,可以节省在请求数据返回后写大量的逻辑函数或者遍历方法去处理事务,所以我才拿出来讲解。 wxs数据处理使用 使用我习惯现在utils文件夹里创建一个common.wxs,然后在使用的wxml引入该文件。具体使用也很简单,如下 在你定义的common.wxs文件里,写你需要处理的函数,然后使用export导出 [代码] var getMax = function(array) { var max = undefined; for (var i = 0; i < array.length; ++i) { max = max === undefined ? array[i] : (max >= array[i] ? max : array[i]); } return max; } module.exports = { getMax: getMax }; [代码] 在.wxml文件需要的地方引入该.wxs文件,其中<wxs>标签包含2个重要属性,[代码]module[代码]和[代码]src[代码]<br> module表示你要导出wxs的方法集合,在wxml里面可以使用该方法名去使用具体的函数<br> src表示你.wxs路径位置引入,代码如下 [代码]<wxs module="common" src="../../utils/common.wxs"></wxs> <view> <text>{{common.getMax(arrNumber)}}</text> </view> [代码] 上面代码里[代码]arrNumber[代码]是你页面.js文件里面定义的数据 [代码]data: { arrNumber: [1,2,9,2,1,5,7] } [代码] 就是如此简单,你已经学会了使用wxs处理数据了,接下来我们来点难的,使用wxs做一个可以随便拖动又不影响小程序性能的手势拖拽事件 wxs拖拽使用 你是否还在使用setData控制元素?为什么不能频繁使用setData,点我查看详情然后通过输出手势坐标来移动元素具体位置?如果是建议你该换个方法了,推荐使用wxs,让你小程序性能上一个档次。 解决思路如下: 我们先在页面的.wxml文件书写初始化的样式内容; 给[代码]view[代码]标签绑定手势事件,其中[代码]touchmove[代码]我使用了阻止冒泡事件绑定是为了防止在苹果机中,元素移动会带着屏幕一起移动,导致滑动手势突然中断不流畅, [代码]clickLive[代码]事件我也用了阻止冒泡事件是为了触发子元素的事件防止点击被父元素拦截而使用,代码如下: [代码]<wxs module="comm" src="../../utils/common.wxs"></wxs> <view class="enterLive liveMove" data-maxWidth="{{windowWidth}}" data-maxHeight="{{windowHeight}}" bind:touchstart="{{comm.liveTouchmove}}" catch:touchmove="{{comm.liveTouchmove}}" bind:touchend="{{comm.liveTouchmove}}"> <view class="live-block" catch:tap="{{comm.clickLive}}"> <image class="liveEnter-img" mode="aspectFit" src="https://img0.baidu.com/it/u=401284325,23907343&fm=26&fmt=auto&gp=0.jpg" /> </view> </view> [代码] 我们发现上面的代码有[代码]windowWidth,windowHeight[代码]两个参数,这是在页面的.js中,是计算当前页面的宽高,用于防止滑块滑出视野范围内,导致无法滑动回来,其中下面代码[代码]getApp().globalData.systemInfo[代码]是读取全局文件[代码]app.js[代码]里面拿值的,那里我有获取系统参数设为全局保存, 而[代码]bindEnter[代码]事件是用于待会在[代码].wxs[代码]里面可以触发.js文件内函数示例 [代码]data: { windowWidth: 375, windowHeight: 667, }, ready: function() { let systemInfo = getApp().globalData.systemInfo; let width = 150 * systemInfo.windowWidth / 750; let height = 150 * systemInfo.windowWidth / 750; if (systemInfo) { this.setData({ windowWidth: systemInfo.windowWidth - parseInt(width), windowHeight: systemInfo.windowHeight - parseInt(height) }) } }, bindEnter(e) { wx.showToast({ title: '你点击到我啦~', icon: 'none' }) }, [代码] 接下来我们将书写.wxs文件,处理手势输出内容,使页面的滑块可以平静的滑动; 认真看的同学会发现页面的[代码]touchstart,touchmove,touchend[代码]事件我都是绑定同一个函数[代码]liveTouchmove[代码]这里是我想节约函数名称,统一使用一个函数,然后在输出的回调里面判断当前是什么手势 这里的滑块滑动逻辑是:当输出是touchstart手势时,我们记住当前滑块的[代码]starLeft,starTop[代码]值及坐标[代码]starX,starY[代码]值 当我们判断当前是[代码]touchmove[代码]手势时,我们就用当前的x,y坐标值减去开始starX和starY坐标值,得到一个差值[代码]diffX,diffY[代码] 然后我们使用这个[代码]diffX,diffY[代码]差值分别加上滑块刚开始的[代码]starLeft,starTop[代码]值,即可得到我们滑块当前移动的位置 最后我们通过条件判断当前是否超出屏幕即可,我这里做多一步,就是滑块永远停留左右两边,所以要多算一次滑块停留是偏离那一边,在通过[代码]ownerInstance.selectComponent('.liveMove').setStyle[代码]可以给页面元素添加行内样式。 滑动滑动逻辑已经讲完了,就是这么简单 如果你想通过[代码].wxs[代码]函数触发[代码].js[代码]文件内的函数,这里有提供[代码]ownerInstance.callMethod("bindEnter")[代码]方法给你触发.js里面的函数,其中[代码]ownerInstance[代码]是绑定页面函数的第二个回调参数,[代码]callMethod[代码]是官方提供的一个方法,[代码]bindEnter[代码]是.js文件里自己命名的函数方法名称,整体代码如下:更多wxs内置方法,请查看官方文档 [代码]/** * 滑块计算位置 */ var starLeft = 0; var starTop = 0; var starX = 0; var starY = 0; function liveTouchmove(event, ownerInstance) { // console.log(JSON.stringify(event)) // console.log(JSON.stringify(ownerInstance)) var left = 0, top = 0; var diffX = 0, diffY = 0; if(event.type === 'touchstart') { starLeft = event.currentTarget.offsetLeft; starTop = event.currentTarget.offsetTop; starX = event.changedTouches[0].clientX; starY = event.changedTouches[0].clientY; left = starLeft; top = starTop; } else { diffX = event.changedTouches[0].clientX - starX; diffY = event.changedTouches[0].clientY - starY; left = starLeft + diffX; top = starTop + diffY; var maxWidth = event.currentTarget.dataset.maxwidth; var maxHeight = event.currentTarget.dataset.maxheight; if (left > maxWidth) { left = maxWidth; } if (top > maxHeight) { top = maxHeight; } if (left <= 0) { left = 0; } if (top <= 0) { top = 0; } } if (event.type === 'touchend') { if (maxWidth / 2 < left) { left = "calc(100% - 3% - 152rpx)"; } if (maxWidth / 2 > left) { left = '3%'; } } else { left = left + 'px'; } var instance = ownerInstance.selectComponent('.liveMove'); // 返回组件的实例 instance.setStyle({ left: left, top: top +'px', }); } /** * 点击直播入口 * @param */ function clickLive (event, ownerInstance) { ownerInstance.callMethod("bindEnter"); } module.exports = { liveTouchmove: liveTouchmove, clickLive: clickLive, }; [代码] 总结 wxs确实可以解决我们一些性能问题,和wxml函数调用方便,但是我们也要注意几个问题 目前还不支持原生组件的事件、input和textarea组件的 bindinput 事件 1.02.1901170及以后版本的开发者工具上支持交互动画,最低版本基础库是2.4.4 目前在WXS函数里面仅支持console.log方式打日志定位问题,注意连续的重复日志会被过滤掉。 wxs有自己的语法,我理解为不支持ES6及以上语法更多wxs语法可以查看官方文档 以上内容,包括之前写的文章内容,最终会上传到我的gitee里面,请留意。 文章创作不易,喜欢的记得点赞 本文同步掘金号文章 喜欢的记得去点个赞哦
2021-07-11