前言:以前分享了那麼多bootstrap組件的使用經驗,這篇博主打算研究下JS組件的擴展和封裝,咱們來感覺下JQuery爲咱們提供$.Extend的神奇,看看咱們怎麼自定義本身的組件,好比咱們想擴展一個$("#id").MyJsControl({})作咱們本身的組件,咱們該如何去作呢,別急,咱們慢慢來看看過程。html
不少時候,咱們使用jquery.ajax的方式向後臺發送請求,型如jquery
$.ajax({ type: "post", url: "/User/Edit", data: { data: JSON.stringify(postdata) }, success: function (data, status) { if (status == "success") { toastr.success('提交數據成功'); $("#tb_aaa").bootstrapTable('refresh'); } }, error: function (e) { }, complete: function () { } });
這種代碼太常見了,這個時候咱們有這樣一個需求:在本身調用ajax請求的時候,咱們不想每次都寫error:function(e){}這種代碼,可是咱們又想讓它每次都將ajax的錯誤信息輸出到瀏覽器讓用戶可以看到。怎麼辦呢?ajax
要想實現以上效果其實並不難,咱們能夠將$.ajax({})封裝一層,在封裝的公共方法裏面定義error對應的事件便可。確實,這樣能達到咱們的要求,可是並不完美,緣由很簡單:1)在jquery的基礎上面再封裝一層,效率不夠高;2)須要改變調用者的習慣,每次調用ajax的時候須要按照咱們定義的方法的規則來寫,而不能直接用原生的$.ajax({})這種寫法,這是咱們不太想看到。數據庫
既然如此,那咱們如何作到既不封裝控件,又能達到以上要求呢?答案就是經過咱們的$.extend去擴展原生的jquery.ajax。bootstrap
其實實現起來也並不難,經過如下一段代碼就能達到咱們的要求。api
(function ($) { //1.獲得$.ajax的對象 var _ajax = $.ajax; $.ajax = function (options) { //2.每次調用發送ajax請求的時候定義默認的error處理方法 var fn = { error: function (XMLHttpRequest, textStatus, errorThrown) { toastr.error(XMLHttpRequest.responseText, '錯誤消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' }); }, success: function (data, textStatus) { }, beforeSend: function (XHR) { }, complete: function (XHR, TS) { } } //3.若是在調用的時候寫了error的處理方法,就不用默認的 if (options.error) { fn.error = options.error; } if (options.success) { fn.success = options.success; } if (options.beforeSend) { fn.beforeSend = options.beforeSend; } if (options.complete) { fn.complete = options.complete; } //4.擴展原生的$.ajax方法,返回最新的參數 var _options = $.extend(options, { error: function (XMLHttpRequest, textStatus, errorThrown) { fn.error(XMLHttpRequest, textStatus, errorThrown); }, success: function (data, textStatus) { fn.success(data, textStatus); }, beforeSend: function (XHR) { fn.beforeSend(XHR); }, complete: function (XHR, TS) { fn.complete(XHR, TS); } }); //5.將最新的參數傳回ajax對象 _ajax(_options); }; })(jQuery);
若是沒接觸過jquery裏面$.extend這個方法的童鞋可能看不懂以上是什麼意思。好,咱們首先來看看jquery API對$.extend()方法是做何解釋的。瀏覽器
什麼意思呢?咱們來看官方的兩個例子就知道了app
栗子一:函數
var settings = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; $.extend(settings, options);
結果:post
settings == { validate: true, limit: 5, name: "bar" }
栗子二:
var empty = {}; var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; var settings = $.extend(empty, defaults, options);
結果:
settings == { validate: true, limit: 5, name: "bar" } empty == { validate: true, limit: 5, name: "bar" }
以上的兩個簡單例子就說明extend()方法做用就是合併另個對象,有相同的則覆蓋,沒有相同的則添加。就是這麼簡單。
瞭解了$.extend()的做用,咱們就能大概看懂上面那個擴展jquery.ajax的實現了吧。主要的步驟分爲:
1)定義默認的error處理方法。
var fn = { error: function (XMLHttpRequest, textStatus, errorThrown) { toastr.error(XMLHttpRequest.responseText, '錯誤消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' }); }, success: function (data, textStatus) { }, beforeSend: function (XHR) { }, complete: function (XHR, TS) { } }
2)判斷用戶在調用$.ajax({})的時候是否自定了error:function(){},若是定義過,則使用用戶定義的,反之則用默認的error處理方法。
3)使用$.extend()將error默認處理方法傳入$.ajax()的參數中。咱們看options參數時包含$.ajax()方法裏面全部的參數的,而後用默認的fn去擴展它便可。
經過以上三步就可以實現對$.ajax()方法裏面error默認處理方法。這樣擴展,對於咱們使用者來講徹底感受不到變化,咱們仍然能夠$.ajax({});這樣去發送ajax請求,若是沒有特殊狀況,不用寫error處理方法。
使用組件擴展,可以幫助咱們在原有組件上面增長一些和咱們系統業務相關的處理需求,而在使用時,仍是和使用原生組件同樣去調用,免去了在組件上面再封裝一層的臃腫。
上面經過$.extend()方法擴展了$.ajax()的error事件處理方法。下面咱們來封裝一個本身的組件試試,功能很簡單,但比較有說明性。咱們就以select這個組件爲例,不少狀況下,咱們的select裏面的option都是須要從數據庫裏面取數據的,因此通常的作法就是發送一個ajax請求,而後在success方法裏面拼html。如今咱們就封裝一個select遠程取數據的方法。
先上乾貨吧,將寫好的整出來:
(function ($) { //1.定義jquery的擴展方法combobox $.fn.combobox = function (options, param) { if (typeof options == 'string') { return $.fn.combobox.methods[options](this, param); } //2.將調用時候傳過來的參數和default參數合併 options = $.extend({}, $.fn.combobox.defaults, options || {}); //3.添加默認值 var target = $(this); target.attr('valuefield', options.valueField); target.attr('textfield', options.textField); target.empty(); var option = $('<option></option>'); option.attr('value', ''); option.text(options.placeholder); target.append(option); //4.判斷用戶傳過來的參數列表裏面是否包含數據data數據集,若是包含,不用發ajax從後臺取,不然否送ajax從後臺取數據 if (options.data) { init(target, options.data); } else { //var param = {}; options.onBeforeLoad.call(target, options.param); if (!options.url) return; $.getJSON(options.url, options.param, function (data) { init(target, data); }); } function init(target, data) { $.each(data, function (i, item) { var option = $('<option></option>'); option.attr('value', item[options.valueField]); option.text(item[options.textField]); target.append(option); }); options.onLoadSuccess.call(target); } target.unbind("change"); target.on("change", function (e) { if (options.onChange) return options.onChange(target.val()); }); } //5.若是傳過來的是字符串,表明調用方法。 $.fn.combobox.methods = { getValue: function (jq) { return jq.val(); }, setValue: function (jq, param) { jq.val(param); }, load: function (jq, url) { $.getJSON(url, function (data) { jq.empty(); var option = $('<option></option>'); option.attr('value', ''); option.text('請選擇'); jq.append(option); $.each(data, function (i, item) { var option = $('<option></option>'); option.attr('value', item[jq.attr('valuefield')]); option.text(item[jq.attr('textfield')]); jq.append(option); }); }); } }; //6.默認參數列表 $.fn.combobox.defaults = { url: null, param: null, data: null, valueField: 'value', textField: 'text', placeholder: '請選擇', onBeforeLoad: function (param) { }, onLoadSuccess: function () { }, onChange: function (value) { } }; })(jQuery);
先來看看咱們自定義組件如何使用:
首先定義一個空的select
<select id="sel_search_plant" class="form-control"></select>
而後初始化它
$(function(){ $('#sel_search_plant').combobox({ url: '/apiaction/Plant/Find', valueField: 'TM_PLANT_ID', textField: 'NAME_C' }); })
參數很簡單,就不一一介紹了。很簡單有木有~~
var strSelectedValue = $('#sel_search_plant').combobox("getValue");
$('#sel_search_plant').combobox("setValue", "aaa");
其實對於簡單的select標籤,博主以爲這裏的getValu和SetValue意義不大,由於直接經過$('#sel_search_plant').val()就能解決的事,何須要再封一層。這裏僅僅是作演示,試想,若是是封裝成相似select2或者multiselect這種組件,getValue和setValue的意義就有了,你以爲呢?
上面的實現代碼,若是您一眼就能看懂,證實您是常常封組件的大蝦了,下面的就不用看了。若是看不懂,也不要緊,咱們將代碼拆開詳細看看裏面是什麼鬼。
(1)首先看看咱們最常看到的以下寫法:
(function ($) { //....封裝組件邏輯 })(jQuery);
初初看到這種用法,博主也是狂抓,這是什麼鬼嘛,四不像啊。使用多了以後才知道原來這就是一個匿名函數的形式。將它拆開來看以下:
var fn = function($){ //.....組件封裝邏輯 }; fn(jQuery);
也就是說這種寫法就表示先定義一個方法,而後當即調用這個方法,jQuery至關於實參。打開jquery.js的原文件能夠看到,jQuery是這個文件裏面的一個全局變量。
(2)定義本身的組件的代碼:
$.fn.combobox = function (options, param) { };
習慣這種寫法的應該知道,這個就表示向jquery對象添加自定義方法,好比你想使用文章開始的 $("#id").MyJsControl({}) 這種用法,你就能夠這樣定義 $.fn.MyJsControl=function(options){} 。
(3) options = $.extend({}, $.fn.combobox.defaults, options || {}); 這一句,看過上文的朋友應該還記得extend這麼一個方法吧,怎麼樣,又來了你。這句話其實就沒什麼好說的了,合併默認參數和用戶傳進來的參數。
(4)默認參數列表
$.fn.combobox.defaults = { url: null, param: null, data: null, valueField: 'value', textField: 'text', placeholder: '請選擇', onBeforeLoad: function (param) { }, onLoadSuccess: function () { }, onChange: function (value) { } };
若是用戶沒有傳參,就用默認的參數列表。若是你夠細心,你會發現博主以前分享的其餘bootstrap組件的js文件裏面都有這麼一個default參數列表。咱們隨便找兩個:
bootstrap上傳組件
bootstrap table組件
基本都是這麼些用法。這樣來看,是否也能夠本身封一個js組件~~
以上就是博主對js組件擴展以及封裝用法的認識和總結。固然,都是些比較簡單基礎的封裝,若是想要實現相似bootstrap table的組件,那還差得很遠。不過萬丈高樓平地起,只要打好基礎,封一個本身的table組件也不是什麼大問題。文中若是有理解不對的地方,歡迎指出,博主將不勝感激。若是本文可以對你有絲毫幫助,麻煩擡起你的小手點個推薦,博主必定繼續努力,將更好的文章分享給你們。