clickoutside.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import Vue from 'vue';
  2. import { on } from 'element-ui/src/utils/dom';
  3. const nodeList = [];
  4. const ctx = '@@clickoutsideContext';
  5. let startClick;
  6. let seed = 0;
  7. !Vue.prototype.$isServer && on(document, 'mousedown', e => (startClick = e));
  8. !Vue.prototype.$isServer && on(document, 'mouseup', e => {
  9. nodeList.forEach(node => node[ctx].documentHandler(e, startClick));
  10. });
  11. /**
  12. * v-clickoutside
  13. * @desc 点击元素外面才会触发的事件
  14. * @example
  15. * ```vue
  16. * <div v-element-clickoutside="handleClose">
  17. * ```
  18. */
  19. export default {
  20. bind(el, binding, vnode) {
  21. nodeList.push(el);
  22. const id = seed++;
  23. const documentHandler = function(mouseup = {}, mousedown = {}) {
  24. if (!vnode.context ||
  25. !mouseup.target ||
  26. !mousedown.target ||
  27. el.contains(mouseup.target) ||
  28. el.contains(mousedown.target) ||
  29. el === mouseup.target ||
  30. (vnode.context.popperElm &&
  31. (vnode.context.popperElm.contains(mouseup.target) ||
  32. vnode.context.popperElm.contains(mousedown.target)))) return;
  33. if (binding.expression &&
  34. el[ctx].methodName &&
  35. vnode.context[el[ctx].methodName]) {
  36. vnode.context[el[ctx].methodName]();
  37. } else {
  38. el[ctx].bindingFn && el[ctx].bindingFn();
  39. }
  40. };
  41. el[ctx] = {
  42. id,
  43. documentHandler,
  44. methodName: binding.expression,
  45. bindingFn: binding.value
  46. };
  47. },
  48. update(el, binding) {
  49. el[ctx].methodName = binding.expression;
  50. el[ctx].bindingFn = binding.value;
  51. },
  52. unbind(el) {
  53. let len = nodeList.length;
  54. for (let i = 0; i < len; i++) {
  55. if (nodeList[i][ctx].id === el[ctx].id) {
  56. nodeList.splice(i, 1);
  57. break;
  58. }
  59. }
  60. }
  61. };