最近在做asp.net mvc项目时遇到一个关于超链接的问题。很是纠结。
问题描述
有一个公司列表展示页。在用鼠标中键(注意了是滚轮)以下简称中键,点击编辑(超链接)的时候在该条数据的下面直接加在一个编辑的局部视图,功能截图如下:
前端代码如下:
@model IEnumerable<Models.Company> @{ ViewBag.Title = "Companies"; Layout = null; } <table class="table"> <tr> <th> 公司名称 </th> <th> 公司地址 </th> <th class="Recruitmenttitle" style="color: green; width: 20%; height: 30px;"> 操作 </th> </tr> @if (Model != null && Model.Count() > 0) { foreach (var item in Model) { <tr> <td> <a href="@Url.Action("RecruitmentDetails", "Recruitment", new { recruitmentid = item.CompanyID })" target="_blank">@item.CompanyName</a> </td> <td> @Html.DisplayFor(modelItem => item.CompanyAddress) </td> <td> <a href="/Test/Edit?companyID=@item.CompanyID" class="btnEdit" data-target="#edit_@item.CompanyID">编辑</a> @Html.ActionLink("删除", "", new { id = item.CompanyID }) </td> </tr> <tr> <td colspan="3" style="display:none;" id="edit_@item.CompanyID"> </td> </tr> } } </table> <script> $(document).ready(function () { $("table").on("click", ".btnEdit", function (e) { var editDiv = $(this).data("target"); $(editDiv).submit(function () { var $form = $(this).find("form"); var $this = $(this); $.post($form.attr("action"), $form.serialize(), function (data) { if (data.status == "0") { $this.css("display", "none").html(); } else { $this.css("display", "block").html(data); } }); return false; }); $.get($(this).attr("href"), function (data) { $(editDiv).css("display", "block").html(data); }); return false; }); }); </script>
后台很简单:
public ActionResult Edit(string companyID) { if (companyID == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Company company = Company.Companies.Find(c => c.CompanyID == Guid.Parse(companyID)); if (company == null) { return HttpNotFound(); } if (Request.IsAjaxRequest()) { return PartialView(company); } return View(company); }
老调重弹,无非是根据不同类型的请求返回不同的视图。这一切似乎都没有什么问题,但是在ie11下当你试着点击鼠标中键(这里指的是我的滚轮,本人用的是低端鼠标没有真正意义上的单击中键)的时候,奇迹出现了:它会以导航链接的方式重新打开直接打开编辑页局部视图:
问题分析
这一看,想都不用想,中键点击的时候肯定发送的不是ajax请求,因为Request.IsAjaxRequest()判断的实质就是检查消息头部的"X-Requested-With"是否是XMLHttpRequest来检查请求是否为ajax请求。在正常点击按钮后,调试即可证明这一点:
中键点击:
当然想要证明这一点不必这么麻烦,用ie捕获一下请求就知道了:
其实分析了这么久了,这只是表明当点击中键的时候,会导致一个导航请求而非我们想看到的ajax请求。
问题解决
这上面分析了这么多,其实是徒劳的。因为我第一下看到这个问题,会以为这个跟a标签没啥关系。其实这个是a标签在IE11(因为我这边IE11下其它地方我没测试过)下,
当用鼠标中键点击a标签时候都会出现这个问题,也就是说这个问题其实是IE11下无法阻止鼠标中键的默认行为。一小段代码测试以下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>效果测试</title> <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script> <script> $(document).ready(function () { $("a").click(function () { return false; }); }); </script> </head> <body> <div class="normal"> <a href="http://www.baidu.com">Go</a> </div> </body> </html>
测试效果截图:
看到这儿,有人可能要问了:你可以在mousedown事件里面做些手脚看下?
我们就来试下,加上mousedown事件(当然click也是它的一种):
$(document).ready(function () { $("a").on("click mousedown", function () { return false; }); });
还是game over了。效果和上面的一样。
但是很奇怪的是:当我在return false之前加行alert("");居然又是可以的了。有点不明觉厉了(注1)。
另一个不是很好的办法的办法:
当然实现partview的这个功能,可以不使用a标签而改用按钮,到目前为止,我确实没有找到一个很完美的解决办法。其实就是要阻止默认行为。当然这只是说的我,Maybe you have?
未完待续
其实问题并没有真正意义上的解决,博问高分悬赏:http://q.cnblogs.com/q/69623/
众神提供的意见
在此感谢各位热情的意见
如EtherDream说言,暂时用唯有采用<a href="javascript:void(0)">Go</a>这样的办法。
结贴
根据DiQiSoft.Com的建议,最终解决了此问题。方案如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>效果测试</title> <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script> <script> $(document).ready(function () { $("a").on("click", function () { return false; }); }); </script> </head> <body> <div class="normal"> <a href="http://www.baidu.com"><span>Go</span></a> </div> </body> </html>
就是在a标签之间加上<span></span>标签。具体的解释可以看#22楼linkFly 的回复截图如下:
正如linkFly 所言,这个是“治标不治本”的,但是也是十分巧妙的办法。
在此对各位标示感谢!
注1:
之所以在return false之前加上alert("")会看到“默认行为被阻止”的假相,是由于它阻塞了后续代码的执行,而并非真正意义上阻止了默认行为。