1. 程式人生 > >jquery下拉框插件心得

jquery下拉框插件心得

inf slide mic 人的 自己的 原生 處理 哈哈 com

想記錄下自己在開發這個下拉框插件之後的心得,發現寫一篇博客,真是“知之非艱,行之惟艱”。所以再有看到好的文章,就不會再吝嗇自己的“贊”了。

多次想該如何寫比較好呢?最終決定,將以後我可能用得到的東西一條條記錄下來,一條條來寫,這樣比較清晰。

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下拉框插件心得