内容转载自 http://www.css88.com/archives/4821
扩展jQuery插件和方法的作用是非常强大的,它可以节省大量开发时间。这篇文章将概述jQuery插件开发的基本知识,最佳做法和常见的陷阱。
入门
编写一个jQuery插件开始于给jQuery.fn加入新的功能属性,此处添加的对象属性的名称就是你插件的名称
jQuery.fn.myPlugin = function(){ //你自己的插件代码 };
用户非常喜欢的$符号哪里去了? 它仍然存在,但是,为了避免和其他JavaScript库冲突,我们最好将jQuery传递给一个自我执行的封闭程序,jQuery在此程序中映射为$符号,这样可以避免$号被其他库覆写。
(function ($) { $.fn.myPlugin = function () { //你自己的插件代码 }; })(jQuery);
在这个封闭程序中,我们可以无限制的使用$符号来表示jQuery函数。
环境
现在,我们可以开始编写实际的插件代码。 但是,在这之前,我们必须得对插件所处的环境有个概念。 在插件的范围里, this关键字代表了这个插件将要执行的jQuery对象, 这里容易产生一个普遍的误区,因为在其他包含callback的jQuery函数中,this关键字代表了原生的DOM元素。这常常会导致开发者误将this关键字无谓的包在jQuery中,如下所示。
(function ($) { $.fn.myPlugin = function () { //此处没有必要将this包在$号中如$(this),因为this已经是一个jQuery对象。 //$(this)等同于 $($('#element')); this.fadeIn('normal', function () { //此处callback函数中this关键字代表一个DOM元素 }); }; })(jQuery); $('#element').myPlugin();
现在,我们理解了jQuery插件的基础知识,让我们写一个插件,做一些事情。
(function ($) { $.fn.maxHeight = function () { var max = 0; this.each(function () { max = Math.max(max, $(this).height()); }); return max; }; })(jQuery); var tallest = $('div').maxHeight(); //返回高度最大的div元素的高度
在公司的security project(Umbraco), Search功能使用了APIController, 然后写了一个JQuery 插件 Search来填充search result page
Search result page HTML 代码
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage<SearchResults> @{ Layout = "_InnerLayout.cshtml"; Html.RequiresJs("~/scripts/view.search.js", 2); } @Model.Content.LocalisedContent.Body <section id="searchListing" class="row search"> <div id="resultsArea" class="search-results"> <div id="NoResultsMessage" style="display:none;"> <p class="results-title">@Html.Raw(Umbraco.GetDictionaryValue("NoResultsFor")) '<strong class="search-term"></strong>'</p> </div> <div id="HasResultsMessage" style="display:none;"> <p class="results-title">@Html.Raw(Umbraco.GetDictionaryValue("SearchResultsFor")) '<strong class="search-term"></strong>'</p> </div> <div class="results" id="SearchResultsContainer"> <article class="row"> <a href="#"> <div> <h2></h2> <p></p> <p class="link">@Html.Raw(Umbraco.GetDictionaryValue("ReadMore")) ›</p> </div> </a> </article> </div> <ul class="pagination"> <li><a href="#" class="prev"><i class="gi icon-arrow"></i></a></li> <li class="page"><a href="#"></a></li> <li><a href="#" class="next"><i class="gi icon-arrow"></i></a></li> </ul> </div> </section>
用JQuery 写的插件Search 如下 (view.search.js)
(function ($) { $.fn.Search = function (options) { return this.each(function () { var search = $(this); search.resultsArea = search.find("#resultsArea"); search.noResultsMessage = search.resultsArea.find("#NoResultsMessage"); search.hasResultsMessage = search.resultsArea.find("#HasResultsMessage"); search.resultsContainer = search.resultsArea.find("#SearchResultsContainer"); search.searchResultTemplate = search.resultsContainer.find("article").clone(); search.queryField = $("input[name='search']"); search.searchTermLabel = $(".search-term"); search.oldTerm = undefined; search.term = search.queryField.val(); // Paging elements search.paginationWrapper = search.resultsArea.find('ul.pagination'); search.pageTemplate = search.paginationWrapper.find('.page').clone(); search.pagePrevious = search.paginationWrapper.find('.prev'); search.pageNext = search.paginationWrapper.find('.next'); // Page tracking search.pageSize = 5; search.pageNumber = 1; search.totalPages = 0; // Sets up pagination for search results. search.paginate = function (data) { /* PagedResults looks like this: data { items, pageNumber, pageSize, totalItems, totalPages } */ search.totalPages = data.totalPages; search.paginationWrapper.find('.page').remove(); if (search.totalPages > 1) { search.pagePrevious.toggle(data.pageNumber > 1); search.pageNext.toggle(data.pageNumber < search.totalPages); for (i = 1; i < search.totalPages + 1; i++) { var page = search.pageTemplate.clone(); var link = page.find('a'); if (i == data.pageNumber) page.addClass('active'); page.data('page', i); link.text(i); search.pageNext.parent().before(page).before(' '); } search.paginationWrapper.show(0); } else { search.paginationWrapper.hide(0); } } search.previous = function (evt) { return search.goToPage(evt, search.pageNumber - 1); } search.next = function (evt) { return search.goToPage(evt, search.pageNumber + 1); } search.goToPage = function (evt, pageNumber) { search.pageNumber = pageNumber || $(this).data('page'); if (search.pageNumber > search.totalPages) search.pageNumber = search.totalPages - 1; if (search.pageNumber < 1) search.pageNumber = 1; search.search(); return false; } // filter change handler search.handleQuery = function (evt) { search.term = $(this).val(); if (search.oldTerm != search.term) { search.oldTerm = search.term; search.search(); } return false; } search.search = function () { search.resultsArea.addClass("loading"); $.ajax({ type: "GET", url: "/umbraco/api/SearchApi/GetSearchResults/", dataType: "json", data: { filter: search.term, pageNumber: search.pageNumber, pageSize: search.pageSize }, success: function (data) { search.searchTermLabel.text(search.term); search.noResultsMessage.hide(); search.hasResultsMessage.hide(); search.paginate(data); search.resultsContainer.empty(); if (!data.items || data.items.length == 0) { search.noResultsMessage.show(); } else { // Binding search result to UI for (var i = 0; i < data.items.length; i++) { var result = data.items[i]; var resultTemplate = search.searchResultTemplate.clone(); _populateContent(result, resultTemplate); search.resultsContainer.append(resultTemplate); } search.hasResultsMessage.show(); } }, complete: function () { search.searchTermLabel.text(search.term); search.resultsArea.removeClass("loading"); } }); }; _populateContent = function (result, template) { var titleElem = $(template.find("h2")); var linkElem = $(template.find("a")); linkElem.attr("href", result.url); titleElem.html(result.title); template.find("p").first().html(result.content); }; search.queryField.on("keyup", search.handleQuery); // Setup pagination triggers. search.pagePrevious.on("click", search.previous); search.pageNext.on("click", search.next); // Bind to all future page clicks. search.paginationWrapper.on('click', 'li.page', search.goToPage); search.search(); }); } }(jQuery)); $(function () { $('section.search').Search(); });