最新时时彩平台演示 中新时时彩要不要交税 新时时彩三星组六技巧 最新时时彩源码修改 新时时彩遗漏走势图 新时时彩预测方法 新时时彩计算器 新时时彩开奖皇冠网址 新时时彩组三怎么玩 最新时时彩后四稳赚 新时时彩官方开奖网站 新时时彩人工计划 新时时彩开奖漏洞 新时时彩最长遗漏 新时时彩中奖顺序 360新时时彩技巧-轴承资讯 新时时彩停售 最新时时彩杀号高手 新时时彩三星走势图 玩新时时彩有什么技巧 新时时彩3星和尾走势 新时时彩后一公式 重新时时彩网站 新时时彩遗漏统计软件 吉林新时时彩走势图 新时时彩中奖怎么查 新时时彩是什么地方 新时时彩中奖怎么查 新时时彩下载手机版下载 新时时彩贴吧 最新时时彩计划软件 大赢家新时时彩 新时时彩注册送彩金 新时时彩组选投注技巧 新时时彩走势图 新时时彩万能5码 新时时彩模拟 新疆新时时彩往期开奖号码 新时时彩的玩法 新时时彩稳赚计划 最新时时彩70注 新时时彩返奖率 新时时彩杀号定胆360 新时时彩后二杀号 新时时彩振幅走势 最新时时彩教程 新时时彩后台软件 新时时彩几点开始 新时时彩日赚几百 最新时时彩注册送20
用户
 ?#19968;?#23494;码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,登录网站

小程序社区 首页 教程 查看内容

微信单页应用的那些事

Rolan 2019-3-13 00:12

这里介绍了一次在微信WebView中使用Vue做单页应用的过程中遇到的一些问题,也是比较常见的问题。文末有亮点,希望大家都来~背景最近因为快过年了,按照微信以往的尿性,小程序的审核总是有各种条条框框,因此为了让 ...

这里介绍了一次在微信WebView中使用Vue做单页应用的过程中遇到的一些问题,也是比较常见的问题。 文末有亮点,希望大家都来~

背景

最近因为快过年了,按照微信以往的尿性,小程序的审核总是有各种条条框框,因此为了让活动在线上正常进行且进行版本的迭代,(主要是为了能得到多一些的开发时间)我们打算采用h5来做活动。

目录

  • 微信小程序跳转WebView的问题;

  • wx.config 进行初始化比较优雅的书写方式;

  • 微信签名的一些问题;

  • Vue单页应用在微信浏览器内遇到的一些问题(包含微信支付);

  • 单页应用内的通信;

微信小程序跳转WebView的问题

首先,我们先来聊一聊微信跳转到WebView的一些事情,在此之前大家可以先来看看官方给的文档:web-view · 小程序

普通的跳转没什么?#30431;?#30340;,先说说我遇到的问题:

在小程序内进入WebView,我需要把小程序中storage模拟的cookie给带过去,调研了很多资料只得到一个方案,想要从小程序向WebView进行通信的话只能通过拼接URL,那很绝望啊,那个cookie有多长你知道吗:joy:?

解决方案:

其实也比较简单,我们在小程序进入WebView之前会对cookie进行一次操作,将cookie进行md5得到一个较短的字符串,通过这个md5进行拼接得到较短的URL会减少很多的问题。

注意点:

  • 我们写在URL里边的地址需要encodeURIComponent一下,避免在链接中带有中文字符,否则在 iOS 中打开页面会有白屏的问题。

  • WebView中的openid和小程序中的openid是不一样的,因此各位如果需要做用户关联的话最好用unionid。

  • 跳转的WebView地址需要在mp后台里边进行加白名单,不然无法访问,域名要求是https的。

  • 我们可以通过微信开发者工具里边公众?#25945;?#36827;行开发,你可以在里边调试WebView的页面,jssdk的报错也可以在调试工具中体现,最后没有问题再通过代理的方式到?#21482;?#19978;过一遍,这里我用的是Charles进行代理的。

wx.config比较优雅的书写方式

项目在引用JS-SDK的API的时候,必须先注入配置信息,也就是 wx.config ,同一个页面(同一个URL)只需要初始化一次就OK了。 wx.config 代码如下:

wx.config({
    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查?#21019;?#20837;的?#38382;?#21487;以在pc端打开,?#38382;?#20449;息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [] // 必填,需要使用的JS接口列表
});
复制代码

具体的信息大家可以看一下文档,这里有一点需要特别提醒大家,?#21019;?#30721;的时候,一定要严格按照微信文档里要求去写,大小写,数据类型?#23478;?#19982;文档保持一致。微信公众?#25945;?/p>

这些都是‘苦口婆心’的话,你要不信,可以试试╮(╯_╰)╭

我在?#21019;?#30721;的时候?#19981;?#25226;不同的功能写在不同的方法里边,初始化的函数只做初始化的事情,这样感觉比较舒服。

  • 在所有微信接口调用前必须保证引入JS-SDK文件,设置JS接口安全域名。

  • JS-SDK里有用户触发时才调用的API,有一点需要注意一下, wx.config 是一个客户端的异步操作,在使用方法的时候会存在因异步导致的时机问题,所以方法最好写在 wx.ready 中, wx.config 信息验证成功后会执行 wx.ready 方法。

  • 我们最好在初始化的时候习惯性的写上 wx.error 与 wx.ready 同级,这样之后方法出现问题调?#20113;?#26469;也会方便不少,也可以做报错提示。

上边的几个点没问题以后,我来说一下比较优雅的初始化方法,大概逻辑如下:

首?#20219;?#20204;需要在方法外边封装一个Promise的模板,但是我的项目中也用了Jquery,我就直接用了里边的 $.Deferred() 方法

let defer = $.Deferred();
let ready = defer.promise();
复制代码

$.Deferred() 其实就是用来返回一个链式实用对象方法来注册多个回调,里边有多个方法

写好这两个方法以后基本上就完成一半了,激不激动!

按照上边介绍的逻辑, ready 是初始化成功,那么回调就是 resolve 。 error 是初始化失败,回调就是 reject 。然后我们用 defer.promise() 去接收两个状态并返回promise对象,之后你就可以愉快的 then()

了。

注意: deferred.promise() 也可以接受一个 target ?#38382;?#27492;时传入的 target 将被赋予 Promise 的方法,并作为结果返回,而不是创建一个新对象。

// Existing object
var obj = {
    hello: function( name ) {
      alert( "Hello " + name );
    }
  },
  // Create a Deferred
  defer = $.Deferred();
 
// Set object as a promise
defer.promise( obj );
 
// Resolve the deferred
defer.resolve( "John" );
 
// Use the object as a Promise
obj.done(function( name ) {
  obj.hello( name ); // Will alert "Hello John"
}).hello( "Karl" ); // Will alert "Hello Karl"
复制代码

具体的你可以看看官网的介绍

jQuery API Documentation

这一切都准备完了,接下?#27425;?#20204;开始初始化配置

getWxSign(){
	wx.config({
		debug: false, 
		appId: ,
        	timestamp: ,
		nonceStr: ,
		signature: ,
		jsApiList: [],
	});
	wx.error((err) => {
		defer.reject(err);
	});
	wx.ready(() => {
		defer.resolve();
	});
}
复制代码

这两步都完成以后,我们的链式解构就完成了,可以放飞自我的书写。

比如我想要获取微信的收货地址,就可以这么写

ready.then(()=>{
	wx.openAddress({
		success: function (res) {},
		fail: function(err) {},
		cancel: function() {}
	});				
});
复制代码

通过这么一封装,你的代码的可读性就会有一个很大提升,至少看着很舒服(自我感觉)。

?#27604;?#22312;使用这些jssdk的API的时候大家要记得加一个:lock:,不然会有多次调用的情况,可能会出?#22336;?#22238;好几次的情况,?#27604;?#36825;个我没有试过,大家可以zuo一下。

微信签名的一些问题

关于微信签名失效的问题,这里主要是想提一下,因为这一块服务端的代码是另外一个小伙伴写的,所以?#20063;?#27809;有太多的?#23548;?#24494;信签名服务端最?#27809;?#23384;一下access_token。这样可以避免很多不必要的麻烦。

官方是这?#27492;?#30340;:公众?#25945;?#20197;access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,access_token在2小时内有效(7200s),过期需要重新获取,但1天内获取次数有限,开发者需自行存储。

其实在开发之初,服务端的同学还没写完这一块逻辑的时候,前端的同学可以这么去调试,先让服务端获取一次配置信息,然后前端暂时先把这一块?#27492;潰?#36825;样 最少两个小时之内是没问题的,可以提高开发的效率 。

还有一点,在缓存的有效期内提前去刷新新access_token,这个让服务端的同学统一控制,不要各自刷新,这样会出现冲突的情况,错误体现为invalid signature。确认这类错的时候我们需要充分利用官方给的签名校验工具

微信 JS 接口签名校验工具

如果是因为token过期导致的签名失败,基本上在输入token以后就直接提示了,这个时候就要看看是不是服务端的缓存时间出了问题,当时我们遇到问题的原因是服务?#35828;?#23618;关于时间的计算多*60...

?#27604;?#20986;现签名错误还有许多的问题,在确保签名算法没有问题的情况下,可能会如?#24405;?#31181;情况:

  • 年少不知微信虎,?#38382;?#22823;小写没有按照官方要求书写。重点需要注意一下nonceStr,timestamp两个字段。timestamp的数据类型是String,这个也要注意下。

  • 确认URL是页面完整的url。可以通过 location.href.split('#')[0] 确?#24076;?#30446;录的话只要填写都按上一?#37117;?#21487;。

假如地址为:
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
那么你的URL可以写到上一级
https://mp.weixin.qq.com/debug/cgi-bin
复制代码
  • config 与获取ticket的AppID不一致。

  • 还有就是服务端如果没有缓存access_token,我们在调试的时候多刷几下可能就会出现问题了,因为开发的时候我感觉刷个几百上千还是很有可能的。

  • 前端传递的URL可能会encodeURIComponent处理过的,服务端需要decode。

  • 还有一个服务端获取的URL与前端的URL不一致,这个在?#21482;?#19978;打开以后你可以复制一下链接检查一下。

vue单页应用在微信浏览器内遇到的一些问题

因为这回我们活动用的是vue的单页应用去完成的,路由用vue-router的history模式,因此会遇到一个比较烦躁的问题,具体的问题我描述一下场景:

在iOS上商品详情页跳转到订单详情页面进行支付,支付页面需要调起两个方法,而我的wx.config是mounted的时候就初始化的,所以每次进入这个页面都会报一个invalid signature,我就纳闷了, 无意间发现刷新了一下页面就正常了 。有时候不报这个签名问题地址也能使用,但是每次支付的时候他就报地址不对

最后我上网查了半天我就发现,history模?#36739;攏?#31614;名使用的URL是刚进入页面时的URL,为了确认是不是这个问题我把每一页的URL都贴出来,还真是都一样,既然问题确认了,那就好解决了。

解决思路:

在进入页面的时候我们可以先检测一下?#21482;?#30340;类型,前边也说了我是在iOS的系统上遇到的问题,在安卓上就没问题,所以无需要对iOS专门处理一下,只要是识别到iOS的机型,那?#27425;?#23601;把地址给改了,代码可以参考如下:

// 专门兼容iOS上微信签名的问题
beforeRouteEnter(to, from, next) {
	var isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
	if (isiOS && to.path !==  location.pathname) {
		location.assign(to.fullPath)
	} else {
		next();
	}
},
复制代码

?#27604;唬?#35299;决的办法不止这一个,其实有很多的解决方案,就是感觉其实不太优雅,当时其实我的备用方案就是要么用a标签进行页面跳转,或者进入这个页面以后,你可以 reload 一下来更新URL。选择怎样的方法大家自己选择吧。

单页应用内的通信

首?#20219;?#35828;一下场景大家方便理解一下目的。当时在做项目的时候整个项目只有一块功能用到这通信,当时服务端的童鞋让?#20063;?#35201;在表单页面进行提交,因为内容不多,让我把信息带到订单页面结算时一起提交,这个其实就是非父子组件之间的通信,但是这个需要通信的地方没那么多,引入一个vuex感觉太重了,我就直接不考虑这个方案了,就然这个不用,那就直接用eventBus其实也可以,代码如下:

首?#20219;?#20204;需要声明一个eventBus的js文件:

import Vue from 'vue';
var eventBus = new Vue({});
export default eventBus; 
复制代码

接下来你需要传递你的值:

import eventBus from 'eventBus/eventBus.js';
let info = {
	a: '',
	b: ''
};
eventBus.$emit('isVal',info);
复制代码

我们在提交表单的页面加一个 emit 的事件,把填写的内容传出去,接下?#27425;?#20204;就要跳回到订单页面了。

import eventBus from 'eventBus/eventBus.js';
eventBus.$on('isVal',(data)=>{
        //....
});
复制代码

使用 on 进行接收,这样就完成了,其实也是比较简单的逻辑,没涉及?#25945;?#22810;东西,对了这个监听可以放在 mounted 或者 create 里边,建议用 once 就OK了。

我们开发的小程序叫做一番市集,欢迎大家注册体验,可以加微信zyf348519452联系我要邀请码哦。

鲜花
鲜花
鸡蛋
鸡蛋
分享至 : QQ空间
收藏
原作者: Yuanf 来自: 掘金
新时时彩软件