jquery下拉框插件心得
想記錄下自己在開發這個下拉框插件之後的心得,發現寫一篇博客,真是“知之非艱,行之惟艱”。所以再有看到好的文章,就不會再吝嗇自己的“贊”了。
多次想該如何寫比較好呢?最終決定,將以後我可能用得到的東西一條條記錄下來,一條條來寫,這樣比較清晰。
1、寫jquery插件需要的一個結構
// 定義jQuery私有作用域
(function ($) {
// 插件默認屬性
var defaults = {
name1: "value1",
name2: "value1",
... ...
}
// 插件名
$.fn.easySlider = function (options) {
// 將默認屬性和用戶傳入得屬性合並
var options = $.extend(defaults, options);
// this.each(function() {}) 循環對象,支持jQuery選擇器
// return 循環後的對象,支持鏈式調用
return this.each(function () {
});
}
})(jQuery) // 傳入jQuery 對象
View Code
第一次寫 jQuery 插件,有看了別人寫的一些博客,分享一個寫的很好的,自己也是從中受益。https://www.cnblogs.com/xcj26/p/3345556.html
2、寫之前先把要實現的的功能理清楚
我覺得是這樣的,要知道自己想要的功能,實現起來就比邊想邊做好,也不容易亂或者遺漏。就以下面這個為例:
- 單選下拉框
- 最基本的點擊下拉框,彈出下拉選項列表
- 點擊下拉選項,切換選中的內容,同時隱藏下拉選項列表
- 點擊其他區域,隱藏下拉選項列表
- 多選下拉框(在單選下拉框的基礎上)
- 可以點擊多個選項,或者選項上的復選框圖標,選擇多個選項,當然這時點擊選項就不能隱藏下拉選項列表了
3、盡可能讓用的人使用起來方便
第一次寫,想的沒那麽周到,按照自己想要的結構就寫了,以下是我最開始寫的,貼出來不怕人笑話,還有一個多選的就不貼了。
<div style ="z-index: 200" class="singleSelect select hideOptions">
<div class="selecter">
<span>請選擇</span>
</div>
<ul class="optionBox hide">
<li data-value="1" class="option">value1</li>
<li data-value="2" class="option">value2</li>
<li data-value="3" class="option">value3</li>
<li data-value="4" class="option">value4</li>
<li data-value="5" class="option">value5</li>
</ul>
</div>
樣式什麽的都寫了,點擊事件啥的也差不多了,啊哈哈哈,我也寫了一個插件,開心啊!但是別人在用的時候,問題就來了,總不能我每次需要一個下拉框的時候,都要寫這麽一堆標簽吧?而且他們需要通過 <form> 提交表單,按這樣來寫肯定是獲取不到值的,雖然說我專門提供了獲取值的方法,但是也滿足不了需求。後面也看了別人寫的下拉框插件,都有隱藏的原生的下拉框 <select>。
其實是這樣的,用的人只需要像原來那樣使用原生的 <select>(<select>在頁面上不顯示出來),需要什麽功能直接往屬性上加,其他的都放 js 中控制。頁面上顯示的是我們自定義的下拉框(newSelect),也就是上面那一堆標簽,在操作 newSelect 的值的同時操作 <select>,保證他們當前選中的值是一樣的,這樣通過 <form> 提交表單就能獲取到 <select> 的值了。
<select id="select2" class="customSelect" onchange="testChange(this)">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected data-selected="selected">3</option>
<option value="4">4</option>
</select>
之後標簽像這樣寫就可以了。
4、先把想要的html結構在html頁面中寫出來
就比如說我自定義的下拉框結構像下面這樣,如果我先在 html 頁面中把想要的結構、功能都實現了,再按這個結構移到 js 中寫,這樣就很清晰了,不會存在直接在 js 中寫字符串模板,寫到一半,然後不知道接著該是什麽標簽來著這樣的問題。當然直接在 js 中寫也行,就怕出錯,所以覺得明確的先把自己想要的東西寫出來,這樣會比較好一些。
<div style="z-index: 200" class="singleSelect select hideOptions">
<div class="selecter">
<span>請選擇</span>
</div>
<ul class="optionBox hide">
<li data-value="1" class="option">value1</li>
<li data-value="2" class="option">value2</li>
<li data-value="3" class="option">value3</li>
<li data-value="4" class="option">value4</li>
<li data-value="5" class="option">value5</li>
</ul>
</div>
5、如果原生已有的功能,盡可能在原生的基礎上進行改造
這點在第3點也有提到,在沒有這個插件的時候,用的肯定是原生的 <select>,如果能實現使用起來原生差不多,主要是結構不能太復雜,這樣使用起來就比較方便。
6、onchange事件,通過js改變select的值,是不會觸發的,需要通過 trigger("change") 來手動觸發
onChange 事件要在失去焦點(blur)後執行,所以通過 js 改變值是不會觸發 onChange 事件的,自己試一下就知道了。
$("#select").trigger("change");
7、事件綁定只需要調用一次,不用每次循環的時候都去調用
可能有的人會像我這樣,好像只要能給元素綁定事件就行,沒註意那麽多,在看別人的代碼的時候,才會註意到自己代碼的問題。
下面的代碼中,綁定事件是寫在循環當中的,每次都要去綁定一次,這樣就做了很多多余的操作。
// 插件名
$.fn.select = function(options) {
// 下拉框對象循環
$(this).each(function(i, select) {
var defaultOptions = {
checkboxImg: {
defaut: "../imgs/checkbox-default.png",
selected: "../imgs/checkbox-selected.png"
},
prompt: "請選擇",
showTitle: true
};
$.extend(true, allOptions, defaultOptions, options || {});
// 建立新的下拉框
$(select).newSelect();
// dom標簽生成之後,綁定事件
$(document).on("mousedown", ".selecter", function() {
});
$(document).on("mousedown", function() {
});
$(document).on("mousedown", ".option", function(event) {
});
});
}
像下面這樣,控制一下,綁定一次就行。這是一種思路,要避免冗余的操作。
$.fn.select = function(options) {
$(this).each(function(i, select) {
var defaultOptions = {
checkboxImg: {
defaut: "../imgs/checkbox-default.png",
selected: "../imgs/checkbox-selected.png"
},
prompt: "請選擇",
showTitle: true
};
$.extend(true, allOptions, defaultOptions, options || {});
// 建立新的下拉框
$(select).newSelect();
// 這邊做一個控制,執行一次就行
if(!initOnce.fired) {
// 該方法的內容就是 為元素綁定事件
initOnce.fire();
initOnce.fired = true;
}
});
}
8、每個能提取出來的功能點都寫成一個方法,比較清楚
這樣以後改造起來會簡單清晰一些。比如要為下拉框設置值,步驟應該是先獲取當前點擊的值,將值的結果處理成自己想要的結構,再設置值。獲取並處理值結構可以寫成一個方法,設置值寫成一個方法,當然,你也可以按自己的需求來分,就是盡量拆分開來,不然一堆的代碼寫在一起,確實不好看。
9、使用 for(var i=0, len=arr.length; i < len; i++),而不是 for(var i=0; i < arr.length; i++),這樣每次都要去獲取數組的長度
這個其實跟第7點有點像,就是這種思路。
10、下拉選項框要放到<body>下,確保能顯示出來
<div style="z-index: 200" class="singleSelect select hideOptions">
<div class="selecter">
<span>請選擇</span>
</div>
<ul class="optionBox hide"> /* 這個下拉選項框相對於 .select 定位*/
<li data-value="1" class="option">value1</li>
<li data-value="2" class="option">value2</li>
<li data-value="3" class="option">value3</li>
<li data-value="4" class="option">value4</li>
<li data-value="5" class="option">value5</li>
</ul>
</div>
這個問題我遇到了,但是沒有很明白。假如說 .select 的外層容器是 .wraper,不知道 .wraper 到底是怎麽了,可能是 .wraper 的層級比較高 ?導致 .select 內層的定位元素被 .wraper 的高度限制,從而顯示不出來。如果有看得懂我寫的,能明白我說的朋友,幫忙說下是什麽原因。
我猜可能是層級的問題,我也看了別人的插件定位元素是直接寫在 <body> 下面,所以就把下拉選項框 <ul> 放到 <body> 下,這樣就能保證能顯示出來。
11、生成的下拉框與原<select>的唯一性屬性要不同,不然在獲取元素時會存在問題(id,name)
這個在開發中遇到的問題,開發人員通過 name 屬性獲取元素,結果不唯一,就導致了問題。這也不是什麽難題,字符串拼接下就好了,只是需要註意一下。
12、鼠標事件順序,mousedown -> focus -> mouseup -> click -> blur
基本用的都是 click 事件,很少用其他的,導致對鼠標事件順序不了解。
mousedown 鼠標點下
focus 輸入框獲得焦點
mouseup 鼠標松開
click 鼠標點下、松開
blur 輸入框失去焦點
我的插件中,為元素綁定的是 mousedown 事件,為什麽呢?
有一個現象,假如我綁定的是 click 事件,然後在下拉選項框彈出之後,去拖動滾動條,這時下拉選項框是不會隱藏的,因為鼠標還沒松開,所以綁定 mousedown 事件就可以很好的解決這個問題,只要點下去的時候就會隱藏下拉選項框了。
這是我寫的簡陋的下拉框:https://github.com/KumikoYYC/jQuery-select
寫的比較 low,多多包涵,多多指點!
jquery下拉框插件心得