It’s a sad story. One morning, there was still one day left before the version was tested, and I was drawing the page methodically according to the plan. The tragedy began when I clicked on a dropdown popup component with an ellipsis five pages back because the paging component had too many pages. The popup was retracted. Scene reappearance

The problem

The appearance of the problem is very simple, using the component library dropdown component, in the component used in the page component, when clicking on the page component to quickly jump back 5 pages, the popover is retracted. Our expectation is that we will be able to continue, and that the popover will only be retracted when we click on the outside of the popover.

Analysis of the

Finding this problem, I made the following analysis:

  1. Determine that this is a problem and repeat the problem, determine the conditions under which the problem occurs, the problems that can be repeated under certain conditions are the problems. I stably reproduce the problem condition is: the paging component appears 5 pages forward or 5 pages backward, click to no more forward 5 pages or 5 pages backward such a fast jump, the pop-up box will be withdrawn.

  2. I don’t see a specific description of this issue in the component documentation. Then I provide the code in the official running environment, wrote a use the demo (in the actual project code complexity is higher, there may be problems are affected by other factors such as style, using single function demo helps us to quickly determine the scope of the problem, and the official running environment is the component of the latest version of the general use). I found the same problem as I used in the project. You can rule out problems caused by component configuration, component library version is not up to date, and project environment.

  3. Query an issue in an open source project in a component library. Search for a keyword in an issue to see if there is a related issue. If you are lucky enough to find a related issue, there will usually be a discussion about it. Unfortunately, I did not find an issue of related issues, so I had to propose an issue by myself. If you have time and patience to wait for the maintenance person to solve the issue you mentioned, the problem analysis can be finished here.

  4. Looking at the source code for the component, it was clear that I was pressed for time and that the problem had to be fixed as soon as possible, and I wanted to determine what the problem was and see if I could fix it. Soon, I found the source code of relevant components. After locating, I found that v-click-outside instruction was used in the dropdown component of the popbox, which is used to trigger the elements outside the click instruction to fold the popbox. Further in-depth source code, found that the principle of the V-click-outside component, is registered in the Document component of a click listening event, when there is a click event, the listener function will judge, click event occurred elements, whether included in the use of instruction elements. If the listener function returns, the event that otherwise fires the instruction binding (in the case of the popbox component, hide the popbox). The code snippet is as follows

	// el represents the element bound by the directive, and event represents the click event
	constisClickOutside = event.target ! == el && ! el.contains(event.target)if(! isClickOutside) {return
	}

	if (middleware(event, el)) {
			handler(event, el)
	}
Copy the code
  1. Breakpoint debugging After the above steps, I did not find the problem, so I had to break the point to debug the code. After debugging, it was found that the problem was in the section el.contains(Event. Target). The first 5 page elements in the paging component were removed from the page by the V-IF command after being triggered. So at this point, el does not contain elements from the previous 5 pages. That is to say, the previous 5 page element was wrongly judged not to be in the EL element, the instruction bound popup function is triggered, and the popup is retracted.

To solve the problem

The problem has been found, now how to solve the problem, because the problem is in the component, but we can not directly modify the component library code, directly modify the project dependent code, is not conducive to code maintenance, but also to cure the symptoms. It is best to solve this problem by adding code to the project code.

It took a bit of a detour at first, thinking of overwriting the clicked elements with pseudo-elements, trying to confuse e.target by making el. Contains (event.target) true. This does work, but it’s still a bit of a problem with more pages, and I’m not quite sure how this pseudo-element masking allows events to trigger elements that aren’t what they are. More importantly, I can’t remember why I came up with this idea when I was writing this article. Maybe it was inspiration. It really takes inspiration to solve a problem.

After using a devious solution to solve the problem temporarily, I began to think of a more radical solution. Ultimately, the problem is with the V-click-outside directive, and if I can find a way to identify the deleted element as a directive registered element, the problem will be completely solved. After constant trying and thinking, I found that when the click event registration was triggered in the capture phase, there were still click elements that should be deleted in the instruction binding elements. At this point the problem is almost clear and a radical solution appears.

Since the v-click-outside directive introduced by the component is locally registered on the dropdown component, I use the extends of vue to inherit the component’s dropdown component. Re-register the directive V-click-outside in the inherited component, which registers click events on the Document as being triggered by the capture phase.

Because components are inherited and overwritten in the component library, the component library upgrade does not have much impact, and there is no need to rewrite a component, reducing the workload. At this point the problem is solved once and for all.

Output v – click – the out package

After solving the problem, I searched some click-outside related packages on NPM, and found that click events registered on document in these packages were generally triggered in the bubbling stage, that is to say, they all had the problems I encountered in the article. So after a few days of spare time efforts, I open source an open source project based on VUE’s click-outside directive catch-click-outside.

A little thought

In my previous work, I also solved many problems. One reason why I record the process of solving this problem is that I generated some output from this problem, which may be slightly helpful to others. Another important reason is that I have made some detours and encountered some obstacles in the process of solving the problems. However, these problems are gradually clear and solved through continuous thinking and events. I think this process is worth recording. As a reminder of the fact that the resolution process is unremarkable due to the limited writing skills.

Reprint please indicate the source!