Mather

We create our own demons.

Select2 更好的下拉列表(上)

默认分类 0 评

Select2

原生 <select> 标签没有 美化和 DOM 事件,没有模糊搜索,从后端获取数据时要自行插入选项,小码农真是伤不起。于是在 AdminLTE 中找到一款叫 Select2 的 jQuery 插件。它支持多语言、远端数据搜索、个性化主题,这一切还基于简洁易懂的 jQuery。


快速使用

1.在 <head> 标签内加入 CDN 地址,当然别忘了这玩意需要 jQuery

<link href="https://cdn.staticfile.org/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/select2/4.0.3/js/select2.min.js"></script>

2.使用 <select> 标签来初始化该插件:

<select name="brand">
    <option value ="volvo">Volvo</option>
    <option value ="saab">Saab</option>
    <option value="opel">Opel</option>
    <option value="audi">Audi</option>
</select>
$(document).ready(function() {
    $('select').select2({
        placeholder:'Select a state',
    });
});

Result


进阶

往往在项目中会遇到更复杂的需求。从后端获取数据到本地渲染,单选或多选的功能。

本地数据

在请求远端之前,不妨先试试读取本地的数据,供用户选择。Select2 建议使用这样约定好的格式:

var data = [
    { id: 0, text: 'enhancement' },
    { id: 1, text: 'bug' },
    { id: 2, text: 'duplicate' },
    { id: 3, text: 'invalid' },
    { id: 4, text: 'wontfix' }
];
PropTypeExampleDescription
idNumber/String0区分选项的唯一值
textString"bug"选中时显示的文字

id 作为 表单对象的值(value),text 作为选项的文本。这样子规定的好处是既能替代原生下拉列表,又不失去其 表单键值选项显示 功能。

这样尝试在初始化的时候使用 本地的 data 对象作为 Select2 的选项。

觉得搜索没必要?关闭掉就好了

$('select').select2({
    placeholder:'Select a state',
    data: data,
    minimumResultsForSearch: Infinity //Hiding the search box
});

现在来看看可以使用自定义的数据来作子选项了


远端数据

显然可以使用远端数据来实现一个复杂可搜索的下拉列表。官方的栗子使用了 Github 搜索仓库的 API 接口作示范,尝试一步步地来读懂它。

var $ajax = $("select");
$ajax.select2({
    ajax: {
        url: "https://api.github.com/search/repositories",
        dataType: 'json',
        delay: 250,
        data: function (params) {
            return {
                q: params.term, // search term
                page: params.page
            };
        },
        processResults: function (data, params) {
            params.page = params.page || 1;
            return {
                results: data.items,
                pagination: {
                    more: (params.page * 30) < data.total_count
                }
            };
        },
        cache: true
    },
    escapeMarkup: function (markup) {
        return markup;
    },
    minimumInputLength: 1,
    templateResult: formatRepo,
    templateSelection: formatRepoSelection
});

function formatRepo(repo) {
    if (repo.loading) return repo.text;
    var markup = "";
    //ellipsis. looking for follows...
    return markup;
}

function formatRepoSelection(repo) {
    return repo.full_name || repo.text;
}

ajax

  • url 指定了接口的地址。
    栗子中的地址直接访问不能得到想要的数据,必须带一些参数,通过接口文档 可知道,加上 ?q=bootstrap 即可查询名为 bootstrap仓库信息
  • data 需配合上面 url 的规定来组合成正确的查询参数,栗子中通过一个匿名函数处理后返回实际的 qpage 作为接口中的参数。params.term 是用户输入的内容,稍作处理可作为接口的参数, params.page 也是一个自定义的参数值。
  • processResults 对象可对接口返回的结果作处理,results 参数这里头的数据(一般为数组)稍后会用来绘制下拉的列表项。这里取 ajax 返回数据中 items 数组 作为处理结果。items 中单个元素中有一些 id name full_name avatar_url description 数据。

escapeMarkup 返回字符串作为 DOM 树的绘制结果,一般默认即可。

minimumInputLength 用户至少要输入几个字符才触发搜索,也会在界面上提示用户。

templateResult 绘制每条子选项时执行的函数。
传入一个参数,即 processResults 函数处理后 results单个元素,其中包括了一些 id name full_name 等数据 。
通过字符串来创建子选项的模板,使用传入repo参数来将要显示的数据填入模版中。当然在这里还可以判断某些参数是否存在,以绘制不同的子选项。最后返回字符串 markup

templateSelection 子选项被选择后执行的函数。
传入的参数同 templateResult 一样。
返回 full_nametext 来用于显示选中项的描述,让用户知道选中了哪一个选项。如果在 processResults 中对要显示的文本处理过,就不必再次去修改返回的 text

数据流动

select2-1.png

整个流程中,其实是在处理一个相关数组,一个个元素渲染成列表。要注意的是,单条数据中的 id 作为 Select2 区分不同选项的重要依据,处理过后的数据中要确保 id 字段的存在。

Demo

分页

Select2 对分页查询非常友好,在接口设计中 page 等分页参数很常见,在一次查询中后台仅返回限定的条数,余下的数据需要再次请求,减少后端的负担。

processResultspaginationmore 作为 布尔变量决定 该次请求后,下一次是否继续请求

pagination: {
    more: (params.page * 30) < data.total_count
}

后端返回的 data.total_count 为搜索结果的条目数。第一次请求时 params.page 为 1 或不存在。若返回的数据是还有第二页且用户滚动列表到底部时,params.page+1 后重新发出一条网络请求。

select2-page.png

dataparams.pageSelect2 中内置的一个属性,保存着当前页数。若 pagination.more 时,该项 +1 并重新请求后端,返回的数据将添加到列表尾部。

参考资料

官方文档

Github

感谢两位作者 Kevin Brown & Igor Vaynberg

ThinkPHP5 模板引擎 使用备忘

发表评论
撰写评论