99409532c0f5c85f7eca667387b8bfd8343a6097cb757f64e51708c395207521ae2e854d9c00a998215cb4d3b491466184a6d94370bdf717d9ed4e749b02f8 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. function createDocumentHandler(el, binding, vnode) {
  12. return function(mouseup = {}, mousedown = {}) {
  13. if (!vnode ||
  14. !vnode.context ||
  15. !mouseup.target ||
  16. !mousedown.target ||
  17. el.contains(mouseup.target) ||
  18. el.contains(mousedown.target) ||
  19. el === mouseup.target ||
  20. (vnode.context.popperElm &&
  21. (vnode.context.popperElm.contains(mouseup.target) ||
  22. vnode.context.popperElm.contains(mousedown.target)))) return;
  23. if (binding.expression &&
  24. el[ctx].methodName &&
  25. vnode.context[el[ctx].methodName]) {
  26. vnode.context[el[ctx].methodName]();
  27. } else {
  28. el[ctx].bindingFn && el[ctx].bindingFn();
  29. }
  30. };
  31. }
  32. /**
  33. * v-clickoutside
  34. * @desc 点击元素外面才会触发的事件
  35. * @example
  36. * ```vue
  37. * <div v-element-clickoutside="handleClose">
  38. * ```
  39. */
  40. export default {
  41. bind(el, binding, vnode) {
  42. nodeList.push(el);
  43. const id = seed++;
  44. el[ctx] = {
  45. id,
  46. documentHandler: createDocumentHandler(el, binding, vnode),
  47. methodName: binding.expression,
  48. bindingFn: binding.value
  49. };
  50. },
  51. update(el, binding, vnode) {
  52. el[ctx].documentHandler = createDocumentHandler(el, binding, vnode);
  53. el[ctx].methodName = binding.expression;
  54. el[ctx].bindingFn = binding.value;
  55. },
  56. unbind(el) {
  57. let len = nodeList.length;
  58. for (let i = 0; i < len; i++) {
  59. if (nodeList[i][ctx].id === el[ctx].id) {
  60. nodeList.splice(i, 1);
  61. break;
  62. }
  63. }
  64. delete el[ctx];
  65. }
  66. };