Problem scenario: there is a page with embedded tables (including scrollbars) and a large number of input and SELECT. When click Select, the drop-down box appears, the normal situation is shown in Figure 1, but when the scrollbars in the table are rolled, the situation in Figure 2 will occur.
Cause: The element tag of the select drop-down box does not follow the select, but below the body tag, and the Z-index is higher, as shown in Figure 3.
Figure 1
Figure 2
Figure 3
The solution
First, an attempt to set the popper-Append-to-body property to false will not work.
Effective solutions can be found in www.e-learn.cn/topic/28212…
The core idea of the article is,
- Monitor mouse press events;
- When the mouse is pressed, determine whether the clicked element is select, if lock is set to false; If it does not return directly;
- When the mouse is clicked again on a non-SELECT element and Lock is false, the mouse is pressed, the event is lifted (the select drop-down box is closed for purposes), and lock is set to true;
- Listen for the wheel event;
- When the element below the mouse position is Select, select has a built-in scroll bar.
- When the element below the mouse position is not select, enforce the mouse-down, lift event (make the SELECT drop box collapse for purposes), and set lock to true;
1. Create a JS file
// fackClickOutSide.js
Copy the code
let lock = true;
let el = null;
// Custom events, mouse down, up, and allow bubbling
const MousedownEvent = new Event('mousedown', { bubbles: true });
const MouseupEvent = new Event('mouseup', { bubbles: true });
const fakeClickOutSide = () = > {
// Trigger the event
document.dispatchEvent(MousedownEvent);
document.dispatchEvent(MouseupEvent);
lock = true; // console.log('dispatchEvent');
};
const mousedownHandle = e= > {
const classList = e.target.classList;
// This criterion is used to determine whether the click is a dropdown box
// El-select__caret means click on the triangle to bring up the dropdown box, and el-input__inner means click on the entire input box
// If the class name of the company component is different, change it accordingly
if (
(classList && classList.contains('el-select__caret')) ||
(classList && classList.contains('el-input__inner'))
) {
lock = false;
return;
}
if (lock) return;
fakeClickOutSide();
};
const mousewheelHandle = e= > {
// If the current select has a scroll bar, it returns directly
// The original text does not declare null for classList
if( lock || (e.target.classList.length ! = =0 &&
e.target.classList.contains('el-select-dropdown__item')) || (e.target.parentNode.classList ! = =undefined &&
e.target.parentNode.classList.contains('el-select-dropdown__item')))return;
fakeClickOutSide();
};
const eventListener = type= > {
el[type + 'EventListener'] ('mousedown', mousedownHandle);
window[type + 'EventListener'] ('mousewheel', mousewheelHandle);
window[type + 'EventListener'] ('DOMMouseScroll', mousewheelHandle); / / fireFox 3.5 +
};
export default {
mounted() {
el = this.$root.$el;
el.addFakeClickOutSideEventCount = el.addFakeClickOutSideEventCount || 0; ! el.addFakeClickOutSideEventCount &&this.$nextTick(() = > {
eventListener('add');
});
el.addFakeClickOutSideEventCount += 1;
},
destroyed() {
eventListener('remove');
el.addFakeClickOutSideEventCount -= 1; }};Copy the code
2. Use
Inside the component you want to import
import fackClickOutSide from '@/mixin/fackClickOutSide.js';
export default {
name: 'FormWithAnchor'.mixins: [fackClickOutSide],
}
Copy the code
3. Knowledge
1. Event
The Event() constructor creates a new Event.
event = newEvent (typeArg, eventInit);Copy the code
TypeArg: event name;
EventInit: This is an object containing the following fields:
bubbles
: (optional)Boolean
Indicates whether the event bubbles. The default isfalse
.cancelable
(Optional) ABoolean
Indicates whether the event can be cancelled. The default isfalse
.
2. document.dispatch
DispatchEvent () is just triggering execution,
Dom.dispatchevent (eventObject), the parameter eventObject represents the Event object created by the createEvent() method.
Effect: Trigger execution. For example, if the mouse is not pressed down, the event function is triggered to achieve the same effect as the mouse is pressed down.
DOM addEventListener adds an event listener function
element.addEventListener(event, function, useCapture)
Event: Mandatory. A string specifying the event name.
Function: Required. Specifies the function to execute when the event is fired.
UseCapture: Optional. Boolean value that specifies whether the event is executed in the capture or bubble phase. Possible values:
- True: Event handles are executed during the capture phase
- False – : default. The event handle executes during the bubbling phase
4. e.target
Whoever triggers the event is who it is.
The target attribute specifies which DOM element fires the event; The target event attribute returns the target node of the event (the node that triggered the event), such as the element, document, or window that generated the event.