The problem

Using Element popover in a project page, setting trigger=’click’ on the outside will not trigger automatic hiding, but it does on Element’s website (official example). The menu in the project is custom written, so it is suspect of black magic.

To find the reason

  1. Write in the popoverapp.vueInside the root component, discovery can trigger automatic hiding normally.
  2. inapp.vueAdd the mounted hook to thewindow.addEventListener('click', () => console.log('window click===>>>>'))Found that only the outer layer of the menu bar can trigger.
  3. Check the menu bar component and find the code<div class="main" @click.stop="isShowWhole = false">The click event uses the stop modifier (to prevent bubbling), which may prevent the popover external click event from being determined. Remove the stop modifier and find that the external click event is triggered normally.

Verify that the code changes have no side effects

When fixing a bug, you need to be careful not to create additional bugs, so you need to understand the meaning of the modified code

@click.stop=”isShowWhole = false”

In code, clicking on a div with class main will trigger a thumbnail display in the left sidebar. The stop modifier is added to prevent events from bubbling, so you need to make sure you remove stop.

// router.js
let routes = [
    {
      path: '/'.alias: '/admin'.component: Menu,
      children: [...Pages],
    },
    {
      path: The '*'.name: '404'.component: NotFound,
    },
  ];
Copy the code

As can be seen in the route, Menu is rendered as the root route, except 404 pages are its child routes, so there is no need to add the stop modifier, after removing the test has no other impact.

Dig into the Element Popover source code to see why

When you debug an Element component, you can import the source code of the component directly

import ElPopover from 'element-ui/packages/popover';
export default {
    components: {
        CheckboxFilter,
        ElPopover
    },
    ...
}
Copy the code

Then we can debug node_modules’ element source code (dangerous step, need to undo after debugging).

// node_modules/element-ui/packages/popover/src/main.vue
mounted() {
    ...
    if (this.trigger === 'click') {
      on(reference, 'click'.this.doToggle);
      on(document.'click'.this.handleDocumentClick);
    } else if (this.trigger === 'hover') {... }else if (this.trigger === 'focus') {... }}Copy the code

Popover initializes the event binding for trigger=’click’ in mounted hook. On (document, ‘click’, this.handleDocumentClick) binding here is likely to prevent the event from bubbling and triggering the external click to hide the judgment logic.

// node_modules/element-ui/packages/popover/src/main.vue
handleDocumentClick(e) {
  let reference = this.reference || this.$refs.reference;
  const popper = this.popper || this.$refs.popper;

  if(! reference &&this.$slots.reference && this.$slots.reference[0]) {
    reference = this.referenceElm = this.$slots.reference[0].elm;
  }
  if (!this.$el || ! reference ||this.$el.contains(e.target) || reference.contains(e.target) || ! popper || popper.contains(e.target))return;
  this.showPopper = false;
},
Copy the code

If this.$el contains the target of click and triggers this.showPopper = false, document cannot listen to the click event if the menu bar prevents the event from bubbling.

V – clickoutside

Element’s Select component uses the V-clickOutside custom directive, The function is similar to that of Popover’s handleDocumentClick (rather handleDocumentClick is a special clickOutside)

In the above question, we can use v-clickoutside separately. Why is that?

// node_modules/element-ui/packages/popover/src/utils/clickoutside.js! Vue.prototype.$isServer && on(document.'mousedown', e => (startClick = e)); ! Vue.prototype.$isServer && on(document.'mouseup', e => {
  nodeList.forEach(node= > node[ctx].documentHandler(e, startClick));
});
Copy the code

The answer is v-ClickOutside using mouse events, so Click’s preventing bubbling does not invalidate ClickOutside.

conclusion

No additional bugs should be generated in the process of bug solving, and in-depth analysis of the cause of the problem is conducive to the improvement of ability.