jquery下拉框插件心得

邮差的信 提交于 2020-12-16 15:41:06

想记录下自己在开发这个下拉框插件之后的心得,修修改改,最终决定,将以后我可能用得到的一条条来写,这样看起来也比较清晰。

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,多多包涵,多多指点!

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!