本文转载自微信公众号《我们医科大学前端技术》,作者黄勤。转载本文请联系微一大学前端技术公众号。背景在普通的代码编程中,我们会遇到一些团队间的交互问题或者协作问题,需要处理链接跳转之间的问题。如果我们是提供方,需求方来自不同的业务团队,有时甚至来自第三方。当然,不仅限于此,还有很多让你脑袋疼的场景。这时候我们可以提供一个中间页面作为对接的桥梁,负责这个页面的所有对接工作。但是对于过渡页的合理使用和一些注意事项,我想在这里进行一篇小文章来谈谈,我们继续往下看。场景一:不确定多方业务方或不同渠道业务方如果我们是提供商,我们会面对不同的业务方,有的来自不同的协作团队,有的来自不同的渠道(微信、小程序、APP),这时候,中间页面应该发挥作用,它负责根据查询参数跳转到具体的目标页面A、B、C等。目标页面应该只负责页面的具体逻辑,不应该接管其他脏活。下图是场景图的简化版。思路:在中间页面可以处理不同的查询,将目标页面放在targetUrl中,处理完对应的逻辑后跳转到目标页面。这个时候,用户其实是没有察觉的。以下是代码的简化版本。注意:作为提供者,最好提供标准模板。比如appid就是专门用来区分来源的。来源的定义应尽可能标准化。预先定义好了,这些查询参数基本统一了。所以最好对外提供对接文档,注释尽量详细(包括在代码中),以免踩坑(诊断问题或撕...我太难了)//这里是一个数组的例子,如果查询需要处理的逻辑constfnList=[['appid','handleAppid'],['token','handleToken'],['payUrl','handlePayUrl'],['sourceId','handleSourceId'],...];mounted(){this.handleQuery();//处理后跳转到目标页面pagetargetif(this.query.target){location.replace(this.query.target);}},//具体的handleQuery操作handleQuery(){//这里可能会有一些预处理...//处理queryfnList.forEach(([key,fn])=>{if(this.query[key]&&this[fn]){this[fn]();}});},2:同一个业务方但是与customization所需的场景听起来和第一个场景很相似,但还是有区别的。如果作为提供商,都是同一个对接方,只是走的是不同的模式,导致后续的业务流程不同。以图中的例子为例,根据类型不同,目标页面前面有不同的目标页面。这里查询的参数会根据类型携带类型对应的业务参数。提供的目标页面是相同的。但参数将取决于业务本身的需求。简单版代码如下://根据类型区分业务来源checkType(type){returnthis.query.type===type;},mounted(){//可能有somepre-operations......this.handleQuery();},//具体的handleQuery操作handleQuery(){//这里可能会有一些预处理...//从服务包中,需要带上sourceId参数if(this.checkType('serverPack')){constnewQuery={sourceId:query.sourceId,...};this.$router.replace({name:'orderServerPackConfirm',query:newQuery,});return;}//来自XXX的信息,确认页面需要带上osTokenIdif(this.checkType('pcDetail')){confirmQuery.osTokenId=this.query.osTokenId;}//Other.....this.$router.replace({name:'orderConfirm',query:confirmQuery,});},3:处理跨域请求或者需要接口提供参数的情况前两种情况,不管是1还是2,基本上都是在说通过query显式传输,但是也会有是一些我们可能不再适用的场景,如下1:参数太多或者对应的参数值太大,以查询的方式传递,使用接口调用的方式,中间页面自己获取必要的参数就是这样。2:应用A跳转到应用B,此时两个应用之间存在跨域问题。A需要调用一个接口,内容值保存在cookie/storage中,其内容需要传递给应用B使用。针对这种情况,可以在跳转到B应用的过程中添加一个预跳转的中间页面。此时A只负责跳转到中间页面,并将自己调用的接口参数传递给中间页面。页面请求接口,这个是内容值可以稳定存放在B应用中。简单版代码如下://检查查询需要checkQuery(keys=[]){returnkeys.every((key)=>!!this.query[key]);},//区分业务source根据类型checkType(type){returnthis.query.type===type;},mounted(){//可能会有一些前置操作......this.handleQuery();},//具体的handleQuery操作handleQuery(){//这里可能有一些预处理...//详解if(this.checkType('detail')&&this.checkQuery(['skuId','quantity'])){//接口中页请求data=awaitthis.directBuy({skuId:+query.skuId,quantity:+query.quantity,});}//购物车if(this.checkType('cart')&&this.checkQuery(['shopcartId'])){//请求数据的接口=awaitthis.submitCart({shopcartids:JSON.parse(query.shopcartId)});}//other.....this.$router.replace({name:'orderConfirm',query:confirmQuery,});},使用中间页的一些注意事项1:不要滥用中间页中间页确实可以帮助我们解决部分逻辑部分业务场景下的分离问题,至少在面对以上场景时,你不需要担心某些情况下哪个业务方的父亲会提供不同的目标页面,但我们仍然需要评估使用中间件的必要性页面根据项目的实际情况。至少我们应该维护:从必要性、业务耦合、可扩展性的角度,在滥用中间页的后期可能会出现合理的编码,可能会出现从中间页到中间页的跳转(不同开发可能会写跳转页面的逻辑,已经是公共页面),由于文档不清晰或更新不及时等原因,后期维护成本可能会更高。这是我们需要注意的问题。2:对于必要的中间页面,尽量规范query上的公共参数,比如来源appid,统一格式h5环境:p_h5_XXX,app渠道:p_app_XXX,小程序环境:p_miniPorgram_XXX,其他参数类似,定义好的统一标准。对于query上必要的参数,比如目标targetUrl,如果提供的url不存在,提供标准化的错误处理。对于丰富多样的参数来源,如果需要,可以在服务端进行处理,对外提供。可配置接口3:有安全意识,对targetUrl做防漏洞处理,避免不可预测的XSS攻击等。中间页面要考虑targetUrl的安全漏洞,尤其是不需要登录的中间页面。如果黑客发送某个链接,欺骗用户点击看似公司福利界面的链接,欺骗用户点击,用户毫无防备就会跳转到虚假界面,很容易骗取用户相关信息,这是我们在添加中间页面时需要考虑的事情,可以在targetUrl中添加白名单限制。总结以上是我在我们的项目中使用过的一些中间页面的总结。希望能结识一些业务相似的朋友,有所收获。当然,这些只是我目前遇到的一些情况,没想到也没有涉及。到了,欢迎提出你的宝贵建议,一起去江紫吧~黄沁:一个爱笑、爱运动、爱音乐、爱旅游的前端女孩
