1、需求 网站内有一个table做的客户列表,其中一列有个“查看详情”的按钮,点击后会向服务器发起一个请求(参数为该行客户的id信息),然后根据返回值判断是否打开一个新页面(返回true则打开新页;返回为false则toast提示“无法查看!”)。 这个需求其实蛮常见,实现似乎也很简单,但还是遇到一些值得一提的情况。2、方案1)方案一:window.openqueryUserViewAuth(params).then((res) => {
If (res.data.isSuccess) {
Window.open('/newPage')
} else {...}
}) 但是当点击按钮触发弹窗时,被浏览器拦截了,项目负责人认为这个体验是不好的,所以需要考虑如何解决这个问题。 在此之前,先提一下浏览器拦截弹窗的原因,网上搜了下,说是因为“ajax回调中的上下文已不是用户行为了,从安全角度出发,浏览器进行了拦截”,这意味着“在函数内部新建a标签再去触发a标签的click事件”也是不可行的。2)方案二:控制a标签的href跳转 于是有提议说是否可以“直接使用a标签替代table中的按钮,然后当用户点击时根据ajax的返回结果去‘阻止/放行’a标签的href行为”。这个想法听起来不太能做到,实际也确实没成功,不过测试中有点儿小发现,虽然目测没什么实用价值,但还是忍不住提一嘴: ① 首先,如果要阻止a标签的href跳转,常见的伎俩如下;<a href="newPage.html" onclick="return false;">测试</a> ② 但这显然不满足此次的需求,得让返回值是可控的,所以尝试变形;<a href="newPage.html" onmousedown="this.x=fn();" onclick="return this.x;">测试</a>
<script>
function fn() {return false}
</script> ③ 上述②的变形是可以的,但那代码都是同步的,所以→再变;<a href="newPage.html" onmousedown="this.x=fn();" onclick="return this.x;">测试</a>
<script>
function fn() {
setTimeout(function(){return false},0)
}
</script> OK,到这里KO了,见证奇迹的时刻并未降临。3)方案三: 苦思无望,只好再到搜索引擎上找找思路,(其实就是解释弹窗为什么被拦截的那帖子),提到了一个思路“在click事件中先打开一个空白的新窗口,然后再进行ajax请求,请求后再去更改新窗口的url”。这方法不错,但可惜并不适用于此次的项目需求,毕竟如果请求发现res.data.isSuccess为false(即不应该打开新页面),“这时再用close去关”并不是一个好的用户体验,何况如果请求返回过慢,那个新窗口会以空白之身杵在那里很久,也不好。4)结束 后来,项目负责人提出暂通过后端来解决,方案如下:前端直接用a标签做按钮,在href上拼接上get请求的地址(即上述的ajax请求),当用户点击时触发请求,然后再由后端做302重定向。3、求助 各位如果有什么好对策,希望能点拨一下。
1 回答
已采纳
慕勒0069038
TA贡献143条经验 获得超39个赞
很抱歉这几天都没有回复, 赶项目= = ,今天抽空看了一眼,给你写了一个 你试试
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="jquery/js/jquery.min.js"></script> <script> $(document).ready(function (e) { $('span').bind('click',function(e,canjump){ console.log(1); if(!canjump){ e.preventDefault(); $('span').trigger("myclick"); } }); $('span').bind('myclick',function(e){ async function a() { try{ return await new Promise((resolve, reject) => { setTimeout(function () { resolve(true); }, 1000); }); }catch (e){ return await Promise.reject(false); } } a().then(function (canjump) { console.log(13); $('span').trigger("click",[true]); }).catch(function (err) { console.log(err); }) }); }); </script> </head> <body> <a href="test1.html" ><span>测试</span></a> </body> </html>
慕勒0069038
TA贡献143条经验 获得超39个赞
方案2 的 可以参考下 es6(es7) 的 async、await
方案2 你的不成功的原因是 应该是fn() 内部的setTimeout 相当于异步方法, 调用fn的时候 没有return false 出来,
其实有个方法, 就是 成功后弹个确认框(layer就行) ,里面说 即将前往新的页面 ,给一个确定和取消, 确定就window.open(), 这样不就不会被拦截了么
添加回答
举报
0/150
提交
取消