您的位置:首页 > 其它

【译】MVC3 20个秘方-(18)Auto Complete(自动完成)

2011-12-15 13:56 204 查看
问题

当你查找一些特殊的东西,当你输入准确的词时,找到它可能是困难的(或者很耗时)。在输入的时候展示出结果(自动完成),使查找变得更简单。

解决方案

使用JQuery自动完成插件,更新现有图书列表页面上的搜索,当用户键入的时候立即显示结果。

讨论

自动完成插件是不会象jQuery基本库一样自动包含在MVC项目中的,所以需要做的第一件事就是的是下载插件
访问http://jquery.com/。两个主要的文件是必需的:JavaScript文件和CSS文件。把新下载的javascript文件放到你MVC应用程序的script 文件夹下。CSS文件可以直接添加到您的content目录。

这个配方也将介绍在view中使用 rendering sections。在shared文件夹下layout中自动添加了2个javascript文件和1个css文件。这些是Ajax和不唐突的Ajax和网站主css文件。每次加载的内容越多,页面视图加载越慢。与其在每个页面都去包含可能不必要的javascript和css 文件,不如在layout中添加一个新的RenderSection()。这允许特别的view在<head>标签去加载特别的javascript或css,但不是每页都添加他们。

下边是一个更新后的Views/Shared/_Layout.cshtml,他使用了一个新的RenderSection()。

<!DOCTYPE html>

<html>
<head>
<title>_Mobile</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>

<script type="text/javascript">
$(document).ready(function () {
if (window.innerWidth <= 480) {
$("link[rel=stylesheet]").attr({ href: "@Url.Content("~/Content/jquery.mobile-1.0b1.min.css")" });
}
});
</script>

@RenderSection("JavaScriptAndCSS", required: false)
</head>
<body>
<div class="page" data-role="page">
<div id="header" data-role="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay" class="ui-bar">
@Html.Partial("_LogOnPartial")
[ @Html.ActionLink("English", "ChangeLanguage", "Home", new { language = "en" }, null) ]
[ @Html.ActionLink("Français", "ChangeLanguage", "Home", new { language = "fr" }, null) ]
</div>
<div id="menucontainer" class="ui-bar">
<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Home", null, new Dictionary<string, object> {{ "data-role", "button" }})</li>
<li>@Html.ActionLink("About", "About", "Home", null, new Dictionary<string, object> { { "data-role", "button" }})</li>
</ul>
</div>
</div>
<div id="main" data-role="content">
@RenderBody()
</div>
<div id="footer" data-role="footer">
</div>
</div>
</body>
</html>


主要的CSS文件和核心的JQuery文件被留下来了,因为css在每个也都需要,并且绝大多数网页也需要JQuery。然而新的JQuery文件和不唐突的AJAX不是每个页面都需要的。

现在,有两种方式使用Autocomplete 插件:

在javascript中设置要搜索的数据。

当用户输入时通过ajax检索。

在我使用这个插件的经验看来,我发现使用解决方案1时自动完成更快。因为它并不需要每次从数据库中请求数据。然而,使用这种解决方案的限制:只有这么多字符,可传递到function中,大量的JavaScript可能会导致
用户的计算机上页面加载缓慢。经过一些试验和错误,我已经确定神奇的数字是大约40,000个结果。如果结果数量超过此,最好使用选项2;否则,始终坚持,因为搜索选项1是瞬时,而不是有轻微的延迟。

在这个例子中,将搜索书籍,我们没有超过40000,所以将使用选项1。BooksController现在必须更新,以设置ViewBag为book title。自动完成功能需要支持一个JavaScript数组的支持,所以书将管道(|)分开。然后在view中,书将被转换到一个数组,使用JavaScript的split()函数。当用户完成键入他们的结果,他们应该有选择完全匹配标题,因此
这个函数将被更新。如果只有1本书返回并且用户执行了搜索,它会自动重定向到本书详细介绍页面。

我们要在bookcontroller 中更新Index Action 并添加一个私有方法名为:FormatBooksForAutocomplete。

代码如下:

展开查看代码

@model PagedList.IPagedList<MvcApplication.Models.Book>

@if (IsAjax)
{
Layout = null;
}

@section JavascriptAndCSS {
<link rel="stylesheet" href="@Url.Content("~/Content/jquery.autocomplete.css")" type="text/css" />
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.autocomplete.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
}

<h2>@MvcApplication4.Resources.Resource1.BookIndexTitle</h2>

<p>
@Html.ActionLink("Create New", "Create")
</p>
<p>
Show:
@if (ViewBag.CurrentFilter != "")
{
@Ajax.ActionLink("All", "Index", new { sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:All
}
  |  
@if (ViewBag.CurrentFilter != "NewReleases")
{
@Ajax.ActionLink("New Releases", "Index", new { filter = "NewReleases", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:New Releases
}
  |  
@if (ViewBag.CurrentFilter != "ComingSoon")
{
@Ajax.ActionLink("Coming Soon", "Index", new { filter = "ComingSoon", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:Coming Soon
}
</p>
@using (Html.BeginForm())
{
@:Search: @Html.TextBox("Keyword", (string)ViewBag.CurrentKeyword, new { id = "KeywordSearch" }) <input type="submit" value="Search" />
}
@Html.Partial("_Paging")
<table>
<tr>
<th>
@Ajax.ActionLink("Title", "Index", new { sortOrder = ViewBag.TitleSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
@Ajax.ActionLink("Isbn", "Index", new { sortOrder = ViewBag.IsbnSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
Summary
</th>
<th>
@Ajax.ActionLink("Author", "Index", new { sortOrder = ViewBag.AuthorSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
Thumbnail
</th>
<th>
@Ajax.ActionLink("Price", "Index", new { sortOrder = ViewBag.PriceSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
@Ajax.ActionLink("Published", "Index", new { sortOrder = ViewBag.PublishedSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th></th>
</tr>

@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Isbn)
</td>
<td>
@Html.DisplayFor(modelItem => item.Summary)
</td>
<td>
@Html.DisplayFor(modelItem => item.Author)
</td>
<td>
@Html.DisplayFor(modelItem => item.Thumbnail)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Published)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}

</table>

@Html.Partial("_Paging")

<script type="text/javascript">
$(document).ready(function () {
var data = "@ViewBag.BookTitles".split("|");
$("#KeywordSearch").autocomplete(data);
});
</script>


为了实施选项2,一个Ajax搜索,而不是传递数据数组到自动完成函数,您可以传递一个URL。URL将需要接受查询字符串变量:q。这包含用户输入的搜索值。这将用于执行书本上包含部分匹配的搜索,并返回以分隔符分隔的字符串。JQuery文档中含有较多的这样的成品例子,也有其他的例子,去更新的输出结果(可能包括书的封面的缩略图)。

另请参阅

Jquery.Autocomplete, RenderSection
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: