Layui自从v2.6.0版本(2021-03-31)就实现了下拉菜单,不必再使用本组件了,如果你是 v2.6.0 前的layui用户,可使用本组件。建议开发者们升级 layui 到最新版本,使用更有保障的官方插件。
官网下拉插件文档:http://layui-doc.pearadmin.com/doc/modules/dropdown.html。如果你仍然希望在高版本的layui中使用本组件,请点击右侧导航:在高版本中使用。
一、简介预览
dropdown
是一款基于layui框架的下拉框控件,填补了layui原生没有下拉框这个空隙。借助下拉框的操作方式和UI交互,可以带来更加直观、便于操作、模块划分清晰等优势。带来了这些优势的同时又加入了许多意想不到的细节:
- 如果下拉框出现的位置会超出浏览器边缘,那么会自动找一个‘凉快’的地方呆着。
- 在你打开下拉框后又进行了界面滚动,她也不依不舍的跟着你走。
那么先不妨先看看本控件的预览效果:
尝鲜 | 左对齐 | 中对齐 | 右对齐 |
---|---|---|---|
注意:分割线、菜单头功能自版本(v1.0.1)加入。
分割线 | 菜单头 | 带横线的菜单头 |
---|---|---|
hover | 自定义下拉 | 任意触发器 |
---|---|---|
要立刻体验?可以点击此处立即在线体验。
二、安装
只需要点击下载(v2.3.5)将JavaScript文件解压到你的layui扩展目录即可开始使用。
下面示例页面中如何使用:
<html>
<head>
<title>dropdown</title>
<link type="text/css" rel="stylesheet" href="假设这是你原本layui的css目录/layui.css">
<link type="text/css" rel="stylesheet" href="你放css的目录/dropdown.css"><!-- 从v2.1.0开始,css可以不用写了,将会自动加载。 -->
</head>
<body>
<button class="layui-btn layui-btn-sm"
lay-filter="test1"
lay-dropdown="{menus: [{layIcon:'layui-icon-username',txt: '个人中心', event:'usercenter'}, {layIcon: 'layui-icon-set',txt: '设置', event:'set'}, {layIcon: 'layui-icon-logout', txt: '退出登录', event:'loginout'}]}">
<span>下拉菜单</span>
<i class="layui-icon layui-icon-triangle-d"></i>
</button>
<script>
// 把 dropdown.js 放在了你的扩展控件目录,你可以:
layui.config({
base: '你的扩展目录'
}).use(['dropdown'], function () {
var dropdown = layui.dropdown;
// 监听菜单点击
dropdown.onFilter('test1', function (event) {
// ...业务代码
})
});
</script>
</body>
</html>
三、详细使用
1、开启下拉
你需要某个按钮(或dom)点击它时它可以下拉展开一个菜单时,你只需要为这个按钮添加lay-dropdown
属性,在后面填写相应的配置。刷新页面,你就可以点击这个按钮实现下拉框了。是不是很简单。就像这样:
<button class="layui-btn layui-btn-sm"
lay-filter="test1"
lay-dropdown="{menus: [{layIcon:'layui-icon-username',txt: '个人中心', event:'usercenter'}, {layIcon: 'layui-icon-set',txt: '设置', event:'set'}, {layIcon: 'layui-icon-logout', txt: '退出登录', event:'loginout'}]}">
<span>下拉菜单</span>
<i class="layui-icon layui-icon-triangle-d"></i>
</button>
<script>
layui.config({
base: '你的扩展目录'
}).use(['dropdown'], function () {
});
</script>
你或许注意到了,通过给lay-dropdown
传入一个包含菜单条目menus
的对象,就可以立即实现下拉菜单的功能了。有关这个对象的具体内容,请往下看。
2、监听点击事件
要监听下拉菜单的点击事件,使用dropdown.onFilter
方法即可监听,示例代码如下:
<script>
layui.config({
base: '你的扩展目录'
}).use(['dropdown'], function () {
var dropdown = layui.dropdown;
// test1 就是触发下拉的按钮的lay-filter属性的内容
dropdown.onFilter("test1", function (event, menu) {
// 根据上一节的配置来说,这里的event可能为:
// usercenter、set、loginout
// 这就取决于你点击的是哪一个菜单项了。
// menu: 这个参数自 v2.3.4 版本加入。
// 表示对应菜单的配置对象,你可以在配置时
// 添加自己喜欢的任意额外属性,然后这里就可以拿到。
console.log(event, menu);
});
});
</script>
dropdown.onFilter
方法提供了两个参数,第一个是确定多个下拉框唯一性的lay-filter
值,第二个就是回调函数,这个回调函数会传入一个event
,通过它你就可以知道点击的具体是哪一个菜单条目了。
值得注意: 当我们在数据表格里使用下拉控件时,则可以不需要使用 onFilter
来监听了,一旦你为menu条目设置了event后,你就可以按照 Layui 官方文档里:监听行工具事件的方式来进行监听,一样会监听到,同时不会因为使用了下拉框而丢失了这些对表格操作的功能。这得益于与dropdown在设计时使用了$.after
的方式插入下拉dom,每一个下拉框的dom都在每一条数据行dom中,使事件监听直接通过表格的方法也能得以实现,这在不知不觉中达到了不谋而合。
3、自定义下拉内容
这无疑是此下拉控件最具光荣的功能,通过它你可以实现任何你希望的下拉内容,这一刻就是你颅内高潮的moment。
通过配置一个参数template
,传入你的布局模板,就可以实现下拉框显示自定义内容了:
<button
class="layui-btn layui-btn-sm"
lay-dropdown="{template: '#custMenu'}"
>
<span>自定义下拉内容</span>
<i class="layui-icon layui-icon-triangle-d"></i>
</button>
<!-- 下拉内容自定义模板 -->
<script id="custMenu" type="text/html">
<div>
<p>我是自定义下拉内容</p>
</div>
</script>
<script>
layui.config({
base: '你的扩展目录'
}).use(['dropdown'], function () {
var dropdown = layui.dropdown;
});
</script>
4、使用代码初始化
当然了,不可能每个下拉框都是在页面出现就跟随立即出现,有很多时候我们需要把下拉框通过后期进行初始化。常见的场景就是在表格里,我们则需要在表格的done
函数里进行初始化。
这就不得不通过代码来初始化了,通过代码初始化,不仅可以带来html
布局上的精简,还可以拥有更强大的功能和自定义效果。
下面示例了如何进行异步初始化:
<!-- 使用代码 -->
<button class="layui-btn layui-btn-sm" id="mybtn">异步初始化下拉</buton>
<script>
layui.config({
base: '你的扩展目录'
}).use(['dropdown'], function () {
var dropdown = layui.dropdown;
// 通过代码(也就是后期异步初始化)进行初始化下拉
// 这样可以把 mybtn 实现下拉菜单
dropdown.suite("#mybtn", {
menus: [{txt: "按钮1"}, {txt: "按钮2"}]
});
// 这样可以把 mybtn 实现下拉自定义内容
dropdown.suite("#mybtn", {
template: "xxxx自定义模板id",
success: function ($dom) {
// 当自定义内容模板初始化完成
// 此方法会调用. 传入的$dom就
// 包含了你的模板的内容,通过它
// 你可以在这里进行模板内其他组
// 件的初始化。
}
});
});
</script>
可以看到suite
方法帮我们完成了下拉初始化,它又两个参数,第一个参数是一个dom选择器,第二个参数是一个option
配置,关于option
详细内容,请看最后一节。
注意: 使用代码初始化是比较推荐的使用方式,尤其是在表格里使用时,如果你的表格里某些字段允许排序,那么你除了在
done
回调方法中初始化一遍,你还需要在table的排序事件(这需要你自己去监听排序事件了)里进行初始化,毕竟排序了之后,表格内容会被重新绘制,之前的初始化就会丢失,所以你有必要再次进行初始化。
5、使用菜单模板配置
本节内容适用于v2.3.0版本,此版本加入了使用菜单模板来配置菜单的功能。在此版本以前,当你希望某些菜单项时,会在JavaScript代码里编写相当一部分代码来完成这个需求,而这仅仅就为了配置要显示哪些菜单而已。这是由于最初设计不周全导致,不过现在好了,从v2.3.0开始推出了 菜单模板配置 功能,它集合了原本menus规范
、laytpl
和 分散配置代码
所有的优势与一身,让原来冗长的 suite 方法变为名副其实的只需要一行。
此方法具有一定的学习成本,但这是值得的,不用2分钟你就会明白,先废话不多说,直接来看看所谓的 菜单模板配置 是如何使用的:
<!-- 先还是写好触发按钮,可以看到通过 templateMenu 配置,指定了一个要使用的模板。 -->
<button class="layui-btn" lay-dropdown="{templateMenu: '#myMenus'}">下拉菜单</button>
<!-- 定义菜单模板 -->
<script id="myMenus" type="text/plain">
[
[{txt: "个人中心", event: "usercenter"}]
[hr]
[{txt: "详细信息", event: "detail"}]
[{txt: "退出登录", event: "logout"}]
]
</script>
是不是很简单。不过还是有细节需要注意,尽管它看起来很像数组,但是它并不是数组,你可以看到多个之间并没有逗号分割。是的,正如你所想,咱们定义了通过一个[]
约束符来确定菜单和菜单条目。
我们来解读一下这个配置。最外层的 []
表示定义了一列菜单,而里面的各个[]
表示定义了各个菜单条目,这些条目通过一个标准的Javascript对象来实现。
你也许不喜欢[]
你也可以换成别的,通过传入配置templateMenuSptor:'()'
现在你就应该这样写模板了:
<script id="myMenus" type="text/plain">
(
({txt: "个人中心", event: "usercenter"})
(hr)
({txt: "详细信息", event: "detail"})
({txt: "退出登录", event: "logout"})
)
</script>
不过你要始终记住,每个条目的出现形式都必须是标准的Javascript对象。
5.1 使用菜单模板配置 - 进阶
本节内容适用于v2.3.0版,此版本加入了使用菜单模板来配置菜单的功能。现在你大致了解了怎么使用它,但要把它用得得心应手,你需要了解下面这些进阶的内容。
转义:如果你的txt文案部分本身就需要有一个 [
符号或者]
符号,它们正好与我们定义的约束符相同了,这时候,你就必须要借助转义字符的使用来实现,和大多数语言一样,我们使用一个 \
来表示转义。就像下面这样:
<!-- 此处假定我们使用默认的约束符号[]进行定义菜单 -->
<script id="myMenus" type="text/plain">
[
[{txt: "\[个人中心\]", event: "usercenter"}]
...
]
</script>
表达式:由于每个菜单条目通过new Function
的方式取得,所以需要提供标准的JavaScript对象,也正因如此,允许你写一些简单的表达式,比如说:
<script id="myMenus" type="text/plain">
[
[{txt: "个人中心" + (5*2), event: "usercenter"}]
[{txt: "详细信息" + Math.random(), event: "detail"}]
[{txt: "退出登录" , event: "logout"}]
]
</script>
看起来这似乎显得然并卵,但往往有时候这种小玩意能给我们带来出乎意料的惊喜。
有效区域:这样一个模板代码,只有最里面的定义各个条目的Javascript对象部分会影响到最后的结果,其它地方写的字符将会全部忽略掉(但依然不能够在这些地方写和约束符相同的字符,这可能会打乱解析流程)。下面是错误的示范:
<!-- 这些写法错误 -->
<script id="myMenus" type="text/plain">
[ 我是乱入的文字[]YOOOO!
[{txt: "个人中心" + (5*2), event: "usercenter"}]
我也是乱入的文字 ]] OHHHHH!
[{txt: "详细信息" + Math.random(), event: "detail"}]
[{txt: "退出登录" , event: "logout"}]
]
</script>
laytpl模板支持: 正是由于借助laytpl,才使得我们有机会根据不同的数据来显示不同的菜单条目。下面给出一个列子,将根据数据的status字段显示不同的菜单:
<script id="myMenus" type="text/plain">
[
{{# if(d.status == 1) { }}
[{txt: "禁用此账户", event: "banaccount"}]
{{# } else { }}
[{txt: "启用此账户", event: "unbanaccount"}]
{{# } }}
[{txt: "退出登录", event: "logout"}]
]
</script>
可以看到,通过d
字段可以访问到传入模板的数据,这是 laytpl模板
的语法定义,而 status 则是通过 第五节 里配置说明的 data 配置项, 你通过data把数据传入后,在模板这里则可以进行使用。要注意,组件会先对模板进行 laytpl 渲染,然后再解析菜单配置,了解这个顺序,有助于你开发。
多列菜单:以上所有的说明都是将的单列菜单,那如何实现多列菜单呢?很简单,再写一个不就好了,相信你一看便知:
<script id="myMenus" type="text/plain">
[
[{txt: "个人中心", event: "usercenter"}]
[{txt: "详细信息", event: "detail"}]
[{txt: "退出登录", event: "logout"}]
]
[
[{txt: "赠送会员", event: "zshy"}]
[{txt: "禁用账号", event: "banaccount"}]
]
</script>
够简单吧,你想写多少就写多少个,只要你开心,并且不用保证每列菜单个数相同。
菜单条目配置规范:上文提及过多次,菜单条目必须是标准的JavaScript对象,而此对象里的如何配置里面的各个字段,此格式和第五节配置里的menus
文档说明一致。
四、api列表
1、dropdown.suite(selector, option)
代码初始化下拉框,通过参数selector
确定哪一个按钮触发下拉框。option
为下拉框配置,配置见下一节。
2、dropdown.onFilter(filter, cb)
监听菜单点击事件,通过它可以监听使用menus
配置的菜单条目点击事件。对于自定义下拉模板内的dom点击事件,可通过option
提供的success
回调函数进行监听,详见下一节option
配置说明。
3、dropdown.hide(selector) v2.1.0 新增
隐藏指定选择器的下拉框。
4、dropdown.show(selector) v2.1.0 新增
显示指定选择器的下拉框。注意:如果选择器对应的dom没有进行下拉初始化,则此方法会进行初始化。此时会用到参数option,你可以通过第二个参数传入。但是通常建议传入的选择器对应的dom是经过了下拉框初始化的。
特别注意: |
---|
上文中提及的选择器selector ,建议使用属性选择器进行编写,比如说我要选择id为dp_user1 的按钮,可以这样写选择器:#dp_user1 也可以这样写:[id='dp_user1'] ,那么更建议使用后者。为什么呢?因为:当你在表格里使用下拉菜单时,尤其是你用在每行右侧的操作栏里的时候,如果你的字段较多那么右侧被fixed的操作栏实际上是一个原本表格右侧操作栏的一个拷贝,也就是说此时界面上存在着两列操作栏,里面的dom结构完全一样,如果你在你的每一行的工具模板里使用了id选择器,那么此时界面上就必然会存在两个相同的id,虽然说一个页面不能存在相同的id,但事实上即便存在也不会产生毁灭性错误,而这时你如果使用的是#dp_user1 这样的选择器,那么只会选择到第一个符合选择器的元素,另一个便不会被选择到。这时如果你要初始化下拉框,可能就会出现明明代码一模一样,可偏偏就是没有效果。你只需要把你的选择器改成使用属性选择器这样的编写格式即可:[id='dp_user1'] 。 |
5、dropdown.destroy(selector, keepListener) v2.3.4 新增
销毁下拉框,当你不再需要某个下拉框时,可以使用这个方法,不过大多数情况下,你都没必要使用它,这取决于实际场景是否需要。参数keepListener
表示是否在销毁时保留在该下拉框上已经设置过的onFilter
点击事件监听函数,默认为 true
也就是默认保留。
五、lay-dropdown配置详解
无论是通过在html上直接通过属性lay-dropdown
来进行配置,还是通过代码suite
方法进行初始化配置,它们传递的配置参数都适用于本节内容:
1、option 说明
var option = {
// 【可选】对齐方式,默认left,可填:left,center,right
align: "left",
// 【与menus、templateMenu三者必填一个】自定义下拉模板id
// 若同时配置了menus则优先 menus 作为下拉内容。
template: "",
// 【可选】当你使用template自定义模板时,支持通过此
// data 向模板里提供数据,从而实现动态渲染。
data: {},
// 【与menus、template三者必填一个】分离式菜单配置模板id [v2.3.0] 新增
// 若同时配置了menus则优先 menus 作为下拉内容。
templateMenu: "",
// 直接配置菜单模板内容,功能同 templateMenu 字段,区别就是 templateMenu 是指定菜单模板id。
// 而此字段则允许你直接写菜单模板配置内容。[v2.3.3]
templateMenuStr: "",
// 【与templateMenu、template两者必填一个】下拉菜单项,数组,里面放多个对象。
// 若同时配置了menus则优先 menus 作为下拉内容。
menus: [
...
// 分割线 (v1.0.1)
"hr",
// 菜单头 (v1.0.1)
{
// 菜单头文案内容
header: "通用",
// 设置为ture则固定此菜单头到顶部。
// 如果一列菜单里有多个菜单头被设置为固定到顶部,则只会使用最后一个。(v2.3.2)。
fixed: false,
// 菜单头文案对齐方式, 可填:left(默认),center,right
// 如果此菜单头被设置为了固定到顶部,则默认值为 center。
align: "left",
// 是否启用带横线的菜单头。当设置为true时,align字段属性不会生效。
// 如果此菜单头被设为 fixed 的,则此字段无效。
withLine: false
},
// 普通按钮项
{
// 菜单图标,示例: layui-icon-heart-fill
// layui图标大全:https://www.layui.com/doc/element/icon.html
layIcon: "",
// 菜单显示文字
txt: "",
// 自定义菜单文字所在span的class [v2.3.0] 新增
txtClass: "",
// 点击此菜单的事件
event: ""
},
...
],
// 【可选】如果发现下拉框显示出来后被遮挡了
// 通过把此配置值修改大于遮挡层的zindex就好了
zIndex: 891,
// 【可选】触发下拉框的方式,可填: click, hover
showBy: "click",
// 【可选】下拉框最小宽度
minWidth: 10,
// 【可选】 下拉框最大宽度 [v2.3.0] 新增
maxWidth: 500,
// 【可选】下拉框最小高度
minHeight: 10,
// 【可选】下拉框最大高度
maxHeight: 300,
// 【可选】下拉框与触发按钮的间隙大小
gap: 4,
// 【可选】多个下拉框确定唯一性的,和属性 lay-filter 一个作用
filter: "",
// 【可选】通过template参数自定义下拉内容时
// 模板渲染成功此方法调用,$down: 包含你的自定义模板的jquery对象。
success: function ($down) {},
// 【可选】当此下拉框被打开时,此方法会被调用。[v1.0.3]
// $maker 是触发下拉框的jquery对象(就是你按的那个按钮的jquery对象), $down 是包含下拉框的jquery对象。
// 不过要注意,layui-icon(即layui图标)若要成功执行transform动画,你需要为它添加css: display:inlibe-block
onShow: function ($maker, $down) {},
// 【可选】当此下拉框被关闭时,此方法会被调用。[v1.0.3]
// $maker 和 $down 和 onShow 方法的参数是一样的。
// 通过 onShow 和 onHide 你就可以完成对界面交互更加协调的视觉体验。
// 比如:按钮右侧小箭头根据相应状态变化指向。
onHide: function($maker, $down) {},
// 【可选】下来菜单内某个按钮点击后,此函数调起。[v2.3.4]新增
// event 表示对应菜单的event事件,menu 表示对应菜单的配置对象,你可以在配置时
// 添加自己喜欢的任意额外属性,然后这里就可以拿到。
onItemClick: function (event, menu) {},
// 【可选】在界面滚动时,下拉框的行为。[v2.0.0]
// 默认为:follow 跟随按钮,可选值:hidden 表示隐藏
scrollBehavior: "follow",
// 【可选】下拉框背景颜色。[v2.0.0]
backgroundColor: "#FFF",
// 初始化完成后是否立即显示下拉框。 [v2.2.0]新增
immed: false,
// 是否显示下拉框上的箭头。[v2.2.0]新增
arrow: true,
// 分离式菜单配置的条目限定符。[v2.3.0]新增
templateMenuSptor: '[]',
// 多列菜单时,是否显示多列菜单之间的分割线。[v2.3.2]新增
menuSplitor: true,
// 渲染下拉框到界面时,将下拉框渲染到指定位置。[v2.3.4]新增
// next(默认): 渲染到触发按钮后面,与触发按钮是兄弟关系,触发按钮是“兄”
// before: 渲染到触发按钮前面,与触发按钮是兄弟关系,触发按钮是“弟”
// selector_xxx: 渲染到指定选择器对应的dom里面,其中xxx就表示选择器。
appendTo: 'next'
}
2、多列菜单
当你需要配置多列下拉菜单时,你的menus
则应该这样配置:
// 示列定义两列菜单
dropdown.suit("下拉按钮选择器", {
menus: [
[
{txt: "个人中心", event: "xxxx"},
"hr",
{txt: "登出", event: "xx"},
],
[
{txt: "禁用账户", event: "xxx"},
{header: "系统"},
{txt: "高级设置", event: "xxxxx"},
],
]
});
如果你使用菜单模板配置,请前往 5.1小节 的 多列菜单 部分查看相关文档。
3、全局配置
全局配置控制着一些更为底层行为偏好。
dropdown_cssLink: 用于配置自动加载下拉框css样式文件时,样式文件的地址,每个版本都在代码里默认了匹配的样式,但你依然可以通过重写(你需要在head里的script标签里定义它)它来实现修改为你喜欢的样式文件地址,此地址必须符合layui样式模块加载规范。
dropdown_useOwnCss: 用于配置是否使用自己的下拉框css样式文件,它默认是false
即不用你自己手动引入css,下拉框会自动加载线上css。当你把它设置为true
(你需要在head里的script标签里定义它)后,下拉框就不会自动加载css,如果此时你没有自己引入css,则可能下拉框样式错误。
4、在高版本中使用
Layui自从v2.6.0版本(2021-03-31)就官方原生实现了下拉菜单的功能。但依然有小伙伴更青睐本组件,仍然希望使用本下拉框组件,此小节将帮助你实现在高版本的layui中如何使用。首要存在的问题就是命名冲突,本组件和官方下拉菜单命名相同叫dropdown
,现在当你想要使用dropdown
模块时,实际上使用的是官方原生的下拉菜单模块,而不是本组件模块。但本模块设计之初考虑到了未来官方可能加入此同名组件的可能性,提供了一个便利的方法,可以让本组件与官方下拉组件不再冲突。
// 在引入 layui 的js文件之前,最好是在 <head> 节点里面,写上如下代码:
<script>MICROANSWER_DROPDOWAN="mDropdown";</script>
上述代码将更改本组件的模块名称为mDropdown
,这样就和官方模块名区分开来,从而解决冲突。不过兼容还没结束,这里我们将本模块名称修改为了mDropdown
,同时还需要将模块文件的文件名称修改为mDropdown.js
。这时候便大功告成,之后你就可以这样使用本模块了:
<script>
// 把 dropdown.js 放在了你的扩展控件目录,你可以:
layui.config({
base: '你的扩展目录'
}).use(['mDropdown'], function () {
var mDropdown = layui.mDropdown;
// 监听菜单点击
mDropdown.onFilter('test1', function (event) {
// ...业务代码
});
// 等等其它功能代码...
// 本文其它地方的所以函数或配置,就都可以通过 mDropdown 来使用了。
});
</script>
【注意】:直接在节点属性上配置的 lay-dropdown="{...}"
这个配置,也要跟着改为:lay-mDropdown="{...}"
。
六、Github
七、更新历史
- v2.3.5 兼容IE8浏览器,优化菜单上下内边距,修复下拉菜单定位。
- v2.3.4 加入自定义下拉框渲染位置、点击事件源数据传入回调,等。
- v2.3.3 优化多列菜单分割线效果、suite方法支持多次调用。修复与Bootstrap一同使用时,CSS冲突导致的界面控件无法使用问题。新增配置字段
templateMenuStr
。 - v2.3.2 小更新,大功能。加入了固定菜单头功能,和菜单分割线设置。优化了多列菜单里某列菜单很长时只有很长的这一列会出现滚动条。
- v2.3.1 deprecated.
- v2.3.0 重大更新,也依然向下兼容。加入了多列菜单、分离配置菜单、加入了菜单条目文案class,优化了布局和css。
- v2.2.0 优化滚动性能,修复隐藏下拉框方案。新增更多配置参数,详见文档。
- v2.1.0 自动加载css,加入hide、show方法,让你可以通过代码控制下拉框的显示与否了。
- v2.0.0 修复在ie浏览器下的滚动问题,修复局部滚动时不跟随的问题,加入配置支持定义滚动行为。
- v1.0.3 加入 onShow 和 onHide 配置,使能实现更多交互上的体验。
- v1.0.2 优化触发下拉体验,全局同时只允许下拉一个菜单。
- v1.0.1 新增菜单分割线、菜单头功能。