经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » jQuery » 查看文章
使用JQuery自动完成插件Auto Complete详解
来源:jb51  时间:2019/6/19 8:38:16  对本文有异议

问题

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

解决方案

使用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()。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>_Mobile</title>
  5. <link href="@Url.Content(" rel="external nofollow" rel="external nofollow" ~/Content/Site.css")" rel="stylesheet" type="text/css" />
  6. <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
  7. <script type="text/javascript">
  8. $(document).ready(function () {
  9. if (window.innerWidth <= 480) {
  10. $("link[rel=stylesheet]").attr({ href: "@Url.Content("~/Content/jquery.mobile-1.0b1.min.css")" });
  11. }
  12. });
  13. </script>
  14. @RenderSection("JavaScriptAndCSS", required: false)
  15. </head>
  16. <body>
  17. <div class="page" data-role="page">
  18. <div id="header" data-role="header">
  19. <div id="title">
  20. <h1>My MVC Application</h1>
  21. </div>
  22. <div id="logindisplay" class="ui-bar">
  23. @Html.Partial("_LogOnPartial")
  24. [ @Html.ActionLink("English", "ChangeLanguage", "Home", new { language = "en" }, null) ]
  25. [ @Html.ActionLink("Français", "ChangeLanguage", "Home", new { language = "fr" }, null) ]
  26. </div>
  27. <div id="menucontainer" class="ui-bar">
  28. <ul id="menu">
  29. <li>@Html.ActionLink("Home", "Index", "Home", null, new Dictionary<string, object> {{ "data-role", "button" }})</li>
  30. <li>@Html.ActionLink("About", "About", "Home", null, new Dictionary<string, object> { { "data-role", "button" }})</li>
  31. </ul>
  32. </div>
  33. </div>
  34. <div id="main" data-role="content">
  35. @RenderBody()
  36. </div>
  37. <div id="footer" data-role="footer">
  38. </div>
  39. </div>
  40. </body>
  41. </html>

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

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

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

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

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

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

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

代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity;
  5. using System.Linq;
  6. using System.Linq.Dynamic;
  7. using System.Web;
  8. using System.Web.Mvc;
  9. using MvcApplication.Models;
  10. using MvcApplication.Utils;
  11. using PagedList;
  12. namespace MvcApplication.Controllers
  13. {
  14. public class BooksController : Controller
  15. {
  16. private BookDBContext db = new BookDBContext();
  17. //
  18. // GET: /Books/
  19. [OutputCache(Duration = Int32.MaxValue, SqlDependency = "MvcApplication.Models.BookDBContext:books", VaryByParam = "sortOrder;filter;page")]
  20. public ActionResult Index(string sortOrder, string filter, string Keyword, int page = 1)
  21. {
  22. #region ViewBag Resources
  23. ViewBag.Title = Resources.Resource1.BookIndexTitle;
  24. ViewBag.CreateLink = Resources.Resource1.CreateLink;
  25. ViewBag.TitleDisplay = Resources.Resource1.TitleDisplay;
  26. ViewBag.IsbnDisplay = Resources.Resource1.IsbnDisplay;
  27. ViewBag.SummaryDisplay = Resources.Resource1.SummaryDisplay;
  28. ViewBag.AuthorDisplay = Resources.Resource1.AuthorDisplay;
  29. ViewBag.ThumbnailDisplay = Resources.Resource1.ThumbnailDisplay;
  30. ViewBag.PriceDisplay = Resources.Resource1.PriceDisplay;
  31. ViewBag.PublishedDisplay = Resources.Resource1.PublishedDisplay;
  32. ViewBag.EditLink = Resources.Resource1.EditLink;
  33. ViewBag.DetailsLink = Resources.Resource1.DetailsLink;
  34. ViewBag.DeleteLink = Resources.Resource1.DeleteLink;
  35. #endregion
  36. #region ViewBag Sort Params
  37. ViewBag.TitleSortParam = (sortOrder == "Title") ? "Title desc" : "Title";
  38. ViewBag.IsbnSortParam = (sortOrder == "Isbn") ? "Isbn desc" : "Isbn";
  39. ViewBag.AuthorSortParam = (sortOrder == "Author") ? "Author desc" : "Author";
  40. ViewBag.PriceSortParam = (sortOrder == "Price") ? "Price desc" : "Price";
  41. ViewBag.PublishedSortParam = (String.IsNullOrEmpty(sortOrder)) ? "Published desc" : "";
  42. // Default the sort order
  43. if (String.IsNullOrEmpty(sortOrder))
  44. {
  45. sortOrder = "Published desc";
  46. }
  47. ViewBag.CurrentSortOrder = sortOrder;
  48. #endregion
  49. var books = from b in db.Books select b;
  50. #region Keyword Search
  51. if (!String.IsNullOrEmpty(Keyword))
  52. {
  53. books = books.Where(b => b.Title.ToUpper().Contains(Keyword.ToUpper()) || b.Author.ToUpper().Contains(Keyword.ToUpper()));
  54. // Should we redirect because of only one result?
  55. if (books.Count() == 1)
  56. {
  57. Book book = books.First();
  58. return RedirectToAction("Details", new { id = book.ID });
  59. }
  60. }
  61. ViewBag.CurrentKeyword = String.IsNullOrEmpty(Keyword) ? "" : Keyword;
  62. #endregion
  63. #region Filter switch
  64. switch (filter)
  65. {
  66. case "NewReleases":
  67. var startDate = DateTime.Today.AddDays(-14);
  68. books = books.Where(b => b.Published <= DateTime.Today.Date
  69. && b.Published >= startDate
  70. );
  71. break;
  72. case "ComingSoon":
  73. books = books.Where(b => b.Published > DateTime.Today.Date);
  74. break;
  75. default:
  76. // No filter needed
  77. break;
  78. }
  79. ViewBag.CurrentFilter = String.IsNullOrEmpty(filter) ? "" : filter;
  80. #endregion
  81. books = books.OrderBy(sortOrder);
  82. int maxRecords = 1;
  83. int currentPage = page - 1;
  84. // Get all book titles
  85. ViewBag.BookTitles = FormatBooksForAutocomplete();
  86. return View(books.ToPagedList(currentPage, maxRecords));
  87. }
  88. private string FormatBooksForAutocomplete()
  89. {
  90. string bookTitles = String.Empty;
  91. var books = from b in db.Books select b;
  92. foreach (Book book in books)
  93. {
  94. if (bookTitles.Length > 0)
  95. {
  96. bookTitles += "|";
  97. }
  98. bookTitles += book.Title;
  99. }
  100. return bookTitles;
  101. }
  102. //
  103. // GET: /Books/Details/5
  104. public ActionResult Details(int id = 0, string bookTitle = "")
  105. {
  106. Book book = db.Books.Find(id);
  107. return View(book);
  108. }
  109. //
  110. // GET: /Books/Create
  111. public ActionResult Create()
  112. {
  113. return View();
  114. }
  115. //
  116. // POST: /Books/Create
  117. [HttpPost]
  118. public ActionResult Create(Book book, HttpPostedFileBase file)
  119. {
  120. if (ModelState.IsValid)
  121. {
  122. // Upload our file
  123. book.Thumbnail = FileUpload.UploadFile(file);
  124. db.Books.Add(book);
  125. db.SaveChanges();
  126. return RedirectToAction("Index");
  127. }
  128. return View(book);
  129. }
  130. //
  131. // GET: /Books/Edit/5
  132. public ActionResult Edit(int id)
  133. {
  134. Book book = db.Books.Find(id);
  135. return View(book);
  136. }
  137. //
  138. // POST: /Books/Edit/5
  139. [HttpPost]
  140. public ActionResult Edit(Book book, HttpPostedFileBase file)
  141. {
  142. if (ModelState.IsValid)
  143. {
  144. // Delete old file
  145. FileUpload.DeleteFile(book.Thumbnail);
  146. // Upload our file
  147. book.Thumbnail = FileUpload.UploadFile(file);
  148. db.Entry(book).State = EntityState.Modified;
  149. db.SaveChanges();
  150. return RedirectToAction("Index");
  151. }
  152. return View(book);
  153. }
  154. //
  155. // GET: /Books/Delete/5
  156. public ActionResult Delete(int id)
  157. {
  158. Book book = db.Books.Find(id);
  159. return View(book);
  160. }
  161. //
  162. // POST: /Books/Delete/5
  163. [HttpPost, ActionName("Delete")]
  164. public ActionResult DeleteConfirmed(int id)
  165. {
  166. Book book = db.Books.Find(id);
  167. // Delete old file
  168. FileUpload.DeleteFile(book.Thumbnail);
  169. db.Books.Remove(book);
  170. db.SaveChanges();
  171. return RedirectToAction("Index");
  172. }
  173. protected override void Dispose(bool disposing)
  174. {
  175. db.Dispose();
  176. base.Dispose(disposing);
  177. }
  178. }
  179. }

最后book/index view需要更新去初始化jQuery的自动完成。要做的第一件事是使用@节标记,包括必要的JavaScript和CSS文件。接下来,以前创建的搜索文本框更新设置一个键的IDwordSearch。

最后,JavaScript代码添加在视图的底部去在搜索文本框上建立自动完成功能。此JavaScript是有意添加在view的底部,以确保完全呈现给用户,因为在用户的电脑上建立数据是一项工作,Javascript处理可能会“堵塞”页面加载。

(译者:先呈现数据再执行javascript,js不是像传统那样放在head标签里)

这取决于结果的数量。代码如下:

  1. @model PagedList.IPagedList<MvcApplication.Models.Book>
  2. @if (IsAjax)
  3. {
  4. Layout = null;
  5. }
  6. @section JavascriptAndCSS {
  7. <link rel="stylesheet" href="@Url.Content(" rel="external nofollow" rel="external nofollow" ~/Content/jquery.autocomplete.css")" type="text/css" />
  8. <script type="text/javascript" src="@Url.Content("~/Scripts/jquery.autocomplete.js")"></script>
  9. <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
  10. }
  11. <h2>@MvcApplication4.Resources.Resource1.BookIndexTitle</h2>
  12. <p>
  13. @Html.ActionLink("Create New", "Create")
  14. </p>
  15. <p>
  16. Show:
  17. @if (ViewBag.CurrentFilter != "")
  18. {
  19. @Ajax.ActionLink("All", "Index", new { sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  20. }
  21. else
  22. {
  23. @:All
  24. }
  25.   |  
  26. @if (ViewBag.CurrentFilter != "NewReleases")
  27. {
  28. @Ajax.ActionLink("New Releases", "Index", new { filter = "NewReleases", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  29. }
  30. else
  31. {
  32. @:New Releases
  33. }
  34.   |  
  35. @if (ViewBag.CurrentFilter != "ComingSoon")
  36. {
  37. @Ajax.ActionLink("Coming Soon", "Index", new { filter = "ComingSoon", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  38. }
  39. else
  40. {
  41. @:Coming Soon
  42. }
  43. </p>
  44. @using (Html.BeginForm())
  45. {
  46. @:Search: @Html.TextBox("Keyword", (string)ViewBag.CurrentKeyword, new { id = "KeywordSearch" }) <input type="submit" value="Search" />
  47. }
  48. @Html.Partial("_Paging")
  49. <table>
  50. <tr>
  51. <th>
  52. @Ajax.ActionLink("Title", "Index", new { sortOrder = ViewBag.TitleSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  53. </th>
  54. <th>
  55. @Ajax.ActionLink("Isbn", "Index", new { sortOrder = ViewBag.IsbnSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  56. </th>
  57. <th>
  58. Summary
  59. </th>
  60. <th>
  61. @Ajax.ActionLink("Author", "Index", new { sortOrder = ViewBag.AuthorSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  62. </th>
  63. <th>
  64. Thumbnail
  65. </th>
  66. <th>
  67. @Ajax.ActionLink("Price", "Index", new { sortOrder = ViewBag.PriceSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  68. </th>
  69. <th>
  70. @Ajax.ActionLink("Published", "Index", new { sortOrder = ViewBag.PublishedSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
  71. </th>
  72. <th></th>
  73. </tr>
  74. @foreach (var item in Model)
  75. {
  76. <tr>
  77. <td>
  78. @Html.DisplayFor(modelItem => item.Title)
  79. </td>
  80. <td>
  81. @Html.DisplayFor(modelItem => item.Isbn)
  82. </td>
  83. <td>
  84. @Html.DisplayFor(modelItem => item.Summary)
  85. </td>
  86. <td>
  87. @Html.DisplayFor(modelItem => item.Author)
  88. </td>
  89. <td>
  90. @Html.DisplayFor(modelItem => item.Thumbnail)
  91. </td>
  92. <td>
  93. @Html.DisplayFor(modelItem => item.Price)
  94. </td>
  95. <td>
  96. @Html.DisplayFor(modelItem => item.Published)
  97. </td>
  98. <td>
  99. @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
  100. @Html.ActionLink("Details", "Details", new { id = item.ID }) |
  101. @Html.ActionLink("Delete", "Delete", new { id = item.ID })
  102. </td>
  103. </tr>
  104. }
  105. </table>
  106. @Html.Partial("_Paging")
  107. <script type="text/javascript">
  108. $(document).ready(function () {
  109. var data = "@ViewBag.BookTitles".split("|");
  110. $("#KeywordSearch").autocomplete(data);
  111. });
  112. </script>

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号