距离第一篇的发布过了很久,由于此次真的踩了很多坑..之后仍是尽可能不要新立项目好了,就跟立了个flag同样T Thtml
本篇主要内容有如下几点--vue
首先介绍一下项目的背景,脱离了背景谈需求都在瞎逼逼,本次活动页是独立于主站项目(SPA)的新独立项目,可是因为对微信的强依赖,新项目仍是须要挂在主域名下。nginx
这有啥的,让运维同事帮忙配个nginx把主站的某个路径指向新项目目录就好呗~事实上确实是的,一开始配的域名是m.kurisu.fm/my(对..这个是假域名)凡是这个路径的都直接指向vue项目的目录,很完美跑起来了,这个也是微信的安全域名因此登陆应该也是稳妥的。可是问题来了...它无法支付...这个域名并非可支付的域名,因此咱们必需要改动域名。vue-router
咱们的可支付路径是m.kurisu.fm/pay/:id,只好再麻烦一下同事帮忙配个m.kurisu.fm/pay/my的路径了,好啦,restart以后一看,凉了。白屏,静态资源都加载出来了,#app也挂载上了,可是router-view那边没有显示。这是啥玩意?看了下vue-router的文档,发现了这个玩意--应用基路径也就是说咱们应该将router的配置修改一下后端
let link = ''
if (window.location.host === 'm.kurisu.fm') {
link = '/pay/my'
}
export default new Router({
base: link, // 在此设定应用的基路径
/*在window.location.host === 'm.kurisu.fm'的状况下,路由会将path为'/'的路径变为'/pay/my',若是没有这个配置的话router仍是会按'/'的路径去匹配路由,这样用户将会没法正常访问到页面*/
routes: [
{
path: '/',
name: 'JXGlobal',
component: JXGlobal
},
{
path: '/auth',
component: Auth
}
]
})
复制代码
修改以后咱们就能够愉快的进行下面的开发啦~并且还能够悄咪咪的在线上跑微信的各个功能[冷漠]api
说到了router就必然少不了对mode的讨论了,这里两种模式我都想说一说,由于实际开发中都TM用到了,最后我得出的结论是--强烈建议使用hash路由缓存
虽然最后我仍是用了history的模式因为项目的历史缘由,这次开发仍是使用了history的模式,具体缘由会在下阐述。安全
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,因而当 URL 改变时,页面不会从新加载。bash
使用这种模式的时候,你们会发现url会出现一个很奇葩的'#',可是这个模式除了丑了点,真的没有啥问题。特别是在微信上面跑单页应用的时候,简直是良心之选。微信
可是为何最后我没有采用这个模式呢?下面我仍是想结合一下项目的实际,说说我选择的缘由--
根本缘由支付受权目录限制是最多只能配置3个,超过3个将没法配置,而且路径深度不能大于2层用了hash以后咱们的url后面都会有'#/'这样就致使微信支付时匹配的目录有问题。通过测试,微信貌似以后根据'/'来判断路径层级的,因此若是使用了'#/'就表明自然少了一层路径,权衡以后仍是放弃了使用hash模式
关于History模式路由的介绍也已经烂大街了,它主要是依靠HTML5新增的API--history.pushState来实现的,具体实现就不在这里啰嗦了,往后争取出一篇router的详解。
因为种种缘由(详情见上方Hash部分)我选择了history模式跑这个项目,在这期间也是遇到了一些坑的地方。
由于项目主要是跑在微信上的,总的来讲坑的地方就是微信JSSDK对单页应用的兼容差强人意
iOS上微信不会根据history.pushState来更改当前的href这致使的问题可很多,复制连接是错误的、受权可能会不成功、支付会有问题;在安卓上则一点问题都没有。解决方案仍是比较粗暴的,在iOS系统中,断定到须要和微信JSSDK交互的页面就强行刷新一下以保证交互的正常进行。
测试支付的时候发现一个颇有趣的现象,在iOS跑得妥妥的支付调起,到安卓就挂了。在安卓系统中,支付调起了,可是最终付款的弹窗却没出现。对比了两端的支付参数也是如出一辙,问题出在哪呢?挣扎了许久,仍是在网上找到了坑友们的回答--安卓调起支付的url不容许'/'结尾,不然支付将会没法正常调起
因为router有两种模式,因此处理起来也有些许差别,不过总的来讲仍是一致的。
首先,咱们最好有一个独立的页面(组件)来处理受权相关的事件,由于实际开发的状况是可能同时存在多种不一样途径的受权,有一个独立页面有助于咱们很好的与主业务解耦。
而后就是看看微信的文档把受权的连接拼起来,这里须要注意的是redirect_uri必需要设定过白名单的域名,不然是无法正常发起受权的。
能正常的重定向到指定的url以后,恭喜你,你已经完成了受权处理的1%一大步啦。重定向的url会带有code(&state...),咱们只须要拿着这个code向后端请求登陆数据便可。
在这一步,两种路由模式的处理方式就有些许不一样了。
history模式下,咱们能够直接经过$route.query来拿到相关的参数,而后能够继续后面的请求。这是没有将受权分离的作法,可是在此次的项目中,我仍是分离出了一个单独的受权页面,这也给本身埋了很多坑。首先是router.push的用法,一开始测试的时候能够顺利的从微信受权的页面回来,可是回来就不动了,即不请求登陆接口,也不重定向回原页面。后面发现是code被冲掉了,罪魁祸首就是我本身router.push,在push的时候没将参数带上。另一个须要注意的是受权完成以后最好使用window.location.href来进行原页面的回跳,能够避开一些在iOS系统下jssdk的坑。
hash模式下,咱们则不须要像history模式那样到处避坑,可是这里咱们会发现没法用$route.query拿到想要的参数,那是由于从微信跳回来以后咱们的url变成了这样-- m.kurisu.fm/?code=1234#/ 发现问题了吗?'#/'加到了最后,致使$route无法拿到'#/'以前的code,这里只须要本身写个解析window.location.search的工具类就能够轻松解决啦。
function urlQuery2Object (search) {
let result = {}
search.split('?')[1].split('&').forEach(function (part) {
let item = part.split('=')
result[item[0]] = decodeURIComponent(item[1])
})
return result
}
复制代码
因为发起支付的路径有所限制,活动页的二级页面甚至是主页都不能独占一层路由,这该怎么解决呢?最快捷的解决方案就是经过route.query和watch对route的监听来实现页面切换。
最后敲定的url是这样的m.kurisu.fm/pay/my?:id&:sid其中id是此次活动的id(可能会同时有多个活动使用同一套页面),sid则是每一个活动下的子活动页面。
<div class="container__content" v-if="activity_init">
<keep-alive>
<jx-index :f_content="init_data" v-if="!$route.query.sid"></jx-index>
<jx-subpage v-else></jx-subpage>
</keep-alive>
</div>
复制代码
在页面展现上咱们只需判断页面是否存在sid就能够知道应该展现哪一个template,而后对$route的监听则只须要在子活动页面的template中进行。
watch: {
//监听$route的变更
'$route' (to, from) {
if (to.query.sid && (to.query.sid !== from.query.sid)) {
//对子活动页的缓存,如有缓存则优先使用缓存数据,并静默(无loading toast)请求新数据,优化页面体验
if (window.sessionStorage.getItem(String(to.query.id) + String(to.query.sid))) {
let data = window.sessionStorage.getItem(String(to.query.id) + String(to.query.sid))
this.column = JSON.parse(data)
this.page_init = true
this.GetData(false)
} else {
this.GetData(true)
}
}
}
}
复制代码
本系列文章主要仍是记录实际开发过程当中的一些解决方案,本篇主要是围绕在路由相关的问题以及微信在其中的兼容问题,但愿能帮助你们和我规避往后的坑。