「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」
新年快乐!除夕夜快乐!
由于自身Blog正在开发中,所以先行记载于此。(首发于本人语雀,现搬运自此)
最近制作个人网站,决定使用Bootstrap,于是就喜闻乐见的遇到了这个问题,网上虽有解决方案,但是对于5版本来说都无法使用(至少我不行),也可能是我太菜了,不知道哪里不对。于是追了下官方的代码,找着了解决方案如下:
首先确认使用的不是min版本,且为bundle(理论上不是bundle的应该也行,不过我用的是bundle)
然后找到:
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);
EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus);
EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) {
event.preventDefault();
Dropdown.getOrCreateInstance(this).toggle();
});
这边就是监听Dropdown的点击事件的地方,我们在后面追加:
/**
* 使Dropdown支持Hover
*/
var mytttt;
EventHandler.on(document, EVENT_MOUSEENTER, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiHoverHandler);
EventHandler.on(document, EVENT_MOUSEENTER, SELECTOR_MENU, Dropdown.dataApiHoverHandler);
EventHandler.on(document, EVENT_MOUSELEAVE, SELECTOR_MENU, Dropdown.clearMyMenus);
EventHandler.on(document, EVENT_MOUSELEAVE, SELECTOR_DATA_TOGGLE$3, Dropdown.clearMyMenus);
然后在Dropdown类的最后面追加:
/**
* 使Dropdown支持Hover
*/
static dataApiHoverHandler(event) {
const isActive = this.classList.contains(CLASS_NAME_SHOW$6);
const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0];
console.log(getToggleButton);
if (!isActive) {
Dropdown.getOrCreateInstance(getToggleButton).show();
}
clearTimeout(mytttt);
}
static clearMyMenus(event) {
const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$3);
mytttt = setTimeout(() => {
for (let i = 0, len = toggles.length; i < len; i++) {
const context = Dropdown.getInstance(toggles[i]);
Dropdown.getOrCreateInstance(toggles[i]).hide();
// 需要先去掉Dropdown.show()里面的this._element.focus();
}
}, 100);
}
最后去掉Dropdown.show()里的this._element.focus();就可以了!
加入Timeout是为了放止因为1px的差距导致直接隐藏,不需要的可以去掉,有其他需求的可以直接改100那个值。
注意:Dropdown.show()里的this._element.focus();一定要去掉,不然他在失焦后再悬浮的时候会有一个白色边框,特别丑。也可以追一下focus的相关css代码,直接覆盖~
更新:
之前的代码其实会有个问题:如果鼠标快速划过两个DropDown,会使这两个DropDownList一起显示,所以优化了一下:
/**
* 使Dropdown支持Hover
*/
static dataApiHoverHandler(event) {
const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0];
const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$3);
for (let i = 0, len = toggles.length; i < len; i++) {
console.log();
if (!toggles[i].matches(CLASS_NAME_SHOW$6)) {
if (toggles[i] == getToggleButton) {
Dropdown.getOrCreateInstance(getToggleButton).show();
clearTimeout(mytttt[i]);
}
} else {
if (toggles[i] == getToggleButton)
clearTimeout(mytttt[i]);
}
}
}
static clearMyMenus(event) {
const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$3);
for (let i = 0, len = toggles.length; i < len; i++) {
mytttt[i] = setTimeout(() => {
Dropdown.getOrCreateInstance(toggles[i]).hide();
// 需要先去掉Dropdown.show()里面的this._element.focus();
}, 100);
}
}
}
var mytttt = [];
替换掉之前代码的相应部分就可以了!
具体逻辑就是:把所有Timer存起来,然后清除的时候用matches判断一下,如果不是当前的元素,并且已经显示就清除掉Timer,就可以了!
其实如果不考虑性能,可以不加是否已经显示的判断,直接不管是否显示都强行把当前悬浮的元素给显示出来并清除Timer也行。