上两个星期做了一个公司用于推广的小活动,选择了Vue的单页面应用。【Vue单页面应用+微信网页开发】套餐赠送了超值大坑,在这里给大家分享一下我的辛酸,啊不,填坑记录。主要是前端填坑的实现,后台方面没有太多涉猎,小白所记,不正确、不准确的还请多多指教。
坑的方位:
1、微信网页授权登录(前后端分离导致的跨域问题)
2、接入JS-SDK实现分享等功能(history模式副带的页面刷新问题和iOS、Android获取url方式不同的兼容问题)
微信网页授权登录(前后端分离导致的跨域问题)
用户在微信客户端中访问我们的域名,公众号通过微信网页授权机制来获取用户基本信息,进而实现业务逻辑。
由于采用的Vue单页面应用框架(vue-router的history模式)、前后端分离模式,微信授权中涉及签名和token的逻辑在前端ajax请求都会遇到跨域问题,所以要依赖服务端完成。
具体见官方文档:微信网页授权
尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。
具体解决方式:
所以在浏览器302回我们的业务域名之前的一系列操作都要交给后台处理,而通常请求业务域名到达反向代理服务器时就会接收到Nginx返回的页面资源了,所以配置好Nginx让客户端在请求业务域名的时候将请求转到后台,后台进行重定向去实行上面的3步。具体后台实现授权登录的做法请参见后台同事写的:前(单页面)后端完全分离的OAuth2授权和分享
值得注意的是,一开始将业务域名的请求转到后台,后台拉取到信息后又重定向回业务域名来加载页面资源,会让浏览器再次发送相同的请求通过Nginx传到后台,形成死循环,所以我们前后台约定在重定向回来的根url后面加一个标识,来区分是浏览器发起的业务域名请求还是后台重定向回来的url(有标识的就是重定向回来的,就直接走vue的路由来加载页面,不用再次请求后台拿code),前端JS代码去掉标识就可以走正常的vue-router了。
那么多字看着很绕,请让我举个栗子:
比如浏览器一开始请求的是www.happy.com,那么后台最后重定向回来加一个标识(随便你用什么标识,请不要用关键字,比如我用homepage)就成了www.happy.com/homepage,如果一开始请求的是www.happy.com/foo,重定向回来的就是www.happy.com/homepage/foo(带/homepage的就直接进路由)。
再废话估计你要打我了,终于该上代码了。来来来:
是不是超级良心简单的土方。请相信我第二个坑的解决方式会酷炫一点[捂脸]。
先容许我把这个解释一下。在vue-router的配置文件index.js里调用router.beforeEach前置守卫拦截到即将要进入的目标路由对象to,然后通过to.path判断是否有我们的标识,来更改目标路由,从而改变路由的页面。so easy,妈妈再也不用担心我的学习[剪刀手]。
接入JS-SDK实现分享等功能(history模式副带的页面刷新问题和iOS、Android获取url方式不同的兼容问题)
1、vue单页面应用完成指定页面的分享
问题描述:
因为有指定不同页面的分享,所以采用vue-router的history模式(如果使用hash模式,分享出去的地址微信会自动处理掉#后边的部分,这样分享出去的都是同一个页面,不能指定某个页面)。再看如何配置微信分享功能,官方是这样说的:
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用
而history模式每次跳转利用 history.pushState API 来完成 URL 跳转而无须重新加载页面,所以在每次路由url变化时都要重新调用一次api去注入实时的配置信息。
上代码:
First,在vue工程的index.html(入口处)引入sdk:
And then,把用到的config接口和各种分享接口封装在一个单独的文件里面,便于每个不同的组件来配置、调用:
请让我解释一下:
1、在src下新建配置js文件
2、把config接口和各种分享接口封装在initWeChat方法里,利用传参来获取当前路由组件的url和分享配置信息(标题、描述、图片等)
3、通过ready接口处理成功验证
微信官方如是说:
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
在调用分享接口时,请一定记得一点:
配置里面的link一定要与你页面url一致!
配置里面的link一定要与你页面url一致!
配置里面的link一定要与你页面url一致!
4、将这个方法暴露出去给各组件调用
如果你不嫌我啰嗦,那我就再叨叨一下各组件的调用方法(大神请跳过)
先引入我们暴露出来的init方法,然后在组件mounted的时候调用init,传入各配置信息。就是这么自信。
2、iOS、Android获取url方式不同的兼容问题
问题描述:
在写好上述分享配置后测试,发现除第一次进入的页面外iOS都签名失败,Android却是个乖宝宝每次都能正确签名。签名失败会导致非常尴尬的问题,分享出去就像这样:
中间两个分享就成了野鸡页面既视感[尴尬]。这是因为config配置失败(打开debug会弹出‘config:fail, invalid signature’)。为什么我们保证了分享的link和url一致还会失败呢,而且就只有iOS失败,而且iOS在第一次进入的页面是成功的,真的是疑点重重[托腮]。
多次试验(进入应用粘贴url、debug抓取打印url)发现,我们iOS同学的微信浏览器每次抓取的是第一次进入的页面url。让我来举个腻子:
我们假设我们点击进入www.happy.com,然后路由跳转到www.happy.com/bar。进入第二个页面时,Android抓取的url是www.happy.com/bar,而iOS小朋友抓取的还是首页www.happy.com。
定位了bug就解决了70%的问题,针对iOS的微信浏览器的单页面应用这种行为我们该怎么办呢,思索过后决定在签名失败的页面reload一次,手动让iOS抓取一次当前url。
容我解释:在上面写的config文件里有一个wx.error方法是专门捕捉签名错误的,可以在这里面操作,判断客户端是iOS的并且签名失败(绿框是判断条件)那就刷新一次。
好啦,到现在我们的应用应该能正常运转咯~欢迎指导纠正~