1.点击按钮展开下拉列表
2.点击下拉列表中的选项进行选择,随后收起下拉列表
3.点击除下拉列表外的位置(包括按钮),收起下拉列表
完整代码请查看:
https://github.com/wolf-wolf/pullDownList.git
1.angular
2.sublime
#基本结构:
组件的基本HTML结构如下所示:
选择列表3
-
在document上监听click事件,进而关闭打开的下拉列表
//列表是否打开的判断标志
$scope.flag = {
showList: false
};
//在document上监听click函数
$document.bind('click', function(event) {
_closeList();//关闭下拉列表
$scope.$apply();//为了保证angular的数据同步
});
/**
* 关闭列表函数
*/
function _closeList() {
$scope.flag.showList = false;
}
上述方法实现简单,理解容易,但存在问题,如果在同一页面中存在多个组件可供点击,并且存在部分组件针对click事件使用event.stopPropagation()
或event.stopImmediatePropagation()
方法阻止事件冒泡,则点击事件无法到达document,进而无法达到自动关闭下拉列表的效果。
###基本思路
在列表打开时,在body
上添加遮罩层,并将其z-index
属性设置为最高,进而遮挡所有该页面的其他组件,同时监听发生在遮罩层上的点击事件,来达到自动关闭下拉列表的效果。
####JavaScript
/**
* 切换列表关闭和打开状态
* @param {Object} event 事件参数,用于阻止事件冒泡
*/
$scope.toggleList = function(event) {
if ($scope.flag.showList) { //如果列表打开则关闭
_closeList();
} else { //如果列表是关闭状态则,创建遮罩层,并打开列表
var _mask = document.createElement('div');
_mask.className = 'drop-down-mask-' + _uniquePrefix;
_mask.style.position = 'absolute';//使用绝对性为
_mask.style.top = '0';
_mask.style.left = '0';
_mask.style.width = '100%';
_mask.style.height = '100%';
_mask.style.zIndex = '99998';
_mask.style.background = 'rgba(255, 255, 255, 0)';//设置遮罩层背景颜色为透明
//为遮罩层添加click方法
_mask.addEventListener('click', function(event) {
_closeList();
$scope.$apply();
});
$document[0].body.append(_mask);
$scope.flag.showList = true;
}
};
/**
* 关闭列表函数,将列表是否打开的判断标志设置为false,并且清除遮罩层
*/
function _closeList() {
$scope.flag.showList = false;
//获取遮罩层元素
var _mask = angular.element(document.getElementsByClassName('drop-down-mask-' + _uniquePrefix));
if (_mask) {
_mask.remove();//移除遮罩层
}
}
HTML
<div class="main">
<button class="open-btn" ng-click="toggleList($event)">选择列表1button>
<div class="list-wrapper" ng-show="flag.showList">
<ul class="list">
<li class="item" ng-repeat="item in list" ng-click="selectItem($event,item)">
<span class="item-name" ng-bind="item.name">span>
li>
ul>
div>
div>
body
下,body
的position
属性为relative
,遮罩层的position
属性为absolute
,以确保遮盖整个页面缺陷:因为有遮罩层的存在所以在点击非下拉列表的位置时,点击事件发生在遮罩层上,如果想要在下拉列表打开的情况下,将焦点定位到其他组件,则需要二次点击。
TIP:
此方法是select2组件所采用的方式,可通过链接查看官网。
为div
添加tabindex
属性,使其可以获得和失去焦点。监听blur
事件做到自动关闭下拉列表的效果
/**
* 关闭列表
* @param {Object} event 事件参数,用于阻止事件冒泡
*/
$scope.closeList = function(event) {
event.stopPropagation();
_closeList();
}
/**
* 切换列表关闭和打开状态
* @param {Object} event 事件参数,用于阻止事件冒泡
*/
$scope.toggleList = function(event) {
event.stopImmediatePropagation();
if ($scope.flag.showList) {
_closeList();
} else {
$scope.flag.showList = true;
}
};
/**
* 关闭列表函数
*/
function _closeList() {
$scope.flag.showList = false;
}
<div class="main" tabindex="-1" ng-blur="closeList($event)" ng-click="toggleList($event)">
<h4 class="open-btn">选择列表2h4>
<div class="list-wrapper" ng-show="flag.showList">
<ul class="list">
<li class="item" ng-repeat="item in list" ng-click="selectItem($event,item)">
<span class="item-name" ng-bind="item.name">span>
li>
ul>
div>
div>
tabindex
属性,这里将其值置为-1
,目的是保证在使用tab
键进行组件焦点切换时不会切换到本组件blur
事件而非click
事件click
事件,以实现点击按钮切换下拉列表打开状态的效果TIP:
为什么不监听focus
事件:因为在获取焦点后,focus
事件步不再会被触发,则无法通过点击按钮来关闭下拉列表。同时focus
事件发生在click
事件之前,如果两个事件同时绑定打开下拉列表的处理函数,则会产生闪烁效果,具体情况,看官可自行尝试~~
tabindex
属性:请查看W3CSchool
如有错误请多多包涵,敬请反馈,期待一起进步~~~
再见,祝好~~!