zoukankan      html  css  js  c++  java
  • vue 自定义指令心得

    //各个快捷键对应的code
    const hotKeyList = {
      "S": 83,
      "O": 79,
      "Q": 81,
      "R": 82,
      'ESC': 27,
    };
    
    function bindEvent(e, el, arg) {
      if(!el || !arg){
        return
      }
      if (el.displayFlag) {
        // console.log(el) 监听组合快捷键ctrl
        let keyCode = e.keyCode || e.which || e.charCode;
        let ctrlKey = e.ctrlKey || e.metaKey;
        if (arg === 'ESC' && keyCode === hotKeyList[arg]) {
          el.click()
          e.preventDefault();
          e.returnValue = false;
          return false;
        } else {
          if (ctrlKey && keyCode === hotKeyList[arg]) {
            el.click()
            e.preventDefault();
            e.returnValue = false;
            return false;
          }
    
        }
    
    
      }
    
    }
    
    // 递归检测触发的按钮是否会显示
    function checkDisplay(el) {
    
      if (el.localName === "body") {
        return true
      }
      if (el.style.display === 'none') {
        return false
      } else {
        if (el.style.display === 'block') {
          return true
        } else {
          return checkDisplay(el.parentNode)  //递归一定要加retur
        }
      }
    }
    
    
    export default {
      name: "shortcutKey",
      inserted() {
        console.log('inserted')
    //最好不要用bind,因为bind的el.parentNode是取不到的,用insert或是update都可以
      },
    
    
      update(el, binding) {
    
        // console.log('update')
    
        if (hotKeyList[binding.arg]) {
          setTimeout(() => {
            el.displayFlag = checkDisplay(el)
            if (!el.displayFlag) {
              window.removeEventListener('keydown', e => bindEvent(e, el, binding.arg))
            } else {
              window.addEventListener('keydown', e => bindEvent(e, el, binding.arg))
            }
    
          }, 300)
    
        }
    
      },
    
      unbind() {
     //解绑事件,应该是有问题的,因为自定义指令定义的变量不是局部的,第二个指令会覆盖调之前定义的
        window.removeEventListener('keydown', bindEvent)
    
      }
    };
    import Vue from "vue";
    
    const isServer = Vue.prototype.$isServer;
    const on = (function () {
      if (!isServer && document.addEventListener) {
        return function (element, event, handler) {
          if (element && event && handler) {
            element.addEventListener(event, handler, false);
          }
        };
      }
      return function (element, event, handler) {
        if (element && event && handler) {
          element.attachEvent("on" + event, handler);
        }
      };
    })();
    
    const nodeList = [];
    const ctx = "@@clickoutsideContext";
    
    let startClick;
    let seed = 0;
    
    !Vue.prototype.$isServer && on(document, "mousedown", e => (startClick = e));
    
    !Vue.prototype.$isServer &&
      on(document, "mouseup", e => {
        nodeList.forEach(node => node[ctx].documentHandler(e, startClick));
      });
    
    function createDocumentHandler(el, binding, vnode) {
      return function (mouseup = {}, mousedown = {}) {
        if (
          !vnode ||
          !vnode.context ||
          !mouseup.target ||
          !mousedown.target ||
          el.contains(mouseup.target) ||
          el.contains(mousedown.target) ||
          el === mouseup.target ||
          (vnode.context.popperElm &&
            (vnode.context.popperElm.contains(mouseup.target) ||
              vnode.context.popperElm.contains(mousedown.target)))
        )
          return;
    
        if (
          binding.expression &&
          el[ctx].methodName &&
          vnode.context[el[ctx].methodName]
        ) {
          vnode.context[el[ctx].methodName]();
        } else {
          el[ctx].bindingFn && el[ctx].bindingFn();
        }
      };
    }
    
    /**
     * v-clickoutside
     * @desc 点击元素外面才会触发的事件
     * @example
     * ```vue
     * <div v-clickoutside="handleClose">
     * ```
     */
    export default {
      name: "clickoutside",
      bind(el, binding, vnode) {
        nodeList.push(el);
        const id = seed++;
        el[ctx] = {
          id,
          documentHandler: createDocumentHandler(el, binding, vnode),
          methodName: binding.expression,
          bindingFn: binding.value
        };
    
    
      },
    
      update(el, binding, vnode) {
    
    
        el[ctx].documentHandler = createDocumentHandler(el, binding, vnode);
        el[ctx].methodName = binding.expression;
        el[ctx].bindingFn = binding.value;
    
        // 判断指令中是否绑定了函数
        if (binding.expression) {
          // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
          binding.value(startClick);
        }
    
      },
    
      unbind(el) {
        let len = nodeList.length;
    
        for (let i = 0; i < len; i++) {
          if (nodeList[i][ctx].id === el[ctx].id) {
            nodeList.splice(i, 1);
            break;
          }
        }
        delete el[ctx];
      }
    };
  • 相关阅读:
    常用模块
    二分查找算法
    递归函数
    文件操作
    day02--Python基础二(基础数据类型)
    Python学习笔记day01--Python基础
    Python2X和Python3X的区别
    testdisk修复文件系统
    机器学习入门 快速版
    tableau教程 快速入门
  • 原文地址:https://www.cnblogs.com/xmhu/p/10115413.html
Copyright © 2011-2022 走看看