美文网首页
【前端之日常工作】常使用的自定义指令集合

【前端之日常工作】常使用的自定义指令集合

作者: 北极星丶超帅的 | 来源:发表于2019-08-13 15:34 被阅读0次

    指令有:只能输入正整数指令、 只能输入数字和两位小数点指令、按钮权限指令、触摸事件指令、全局loading指令

    /* 
     ** 自定义指令
     */
    
    import Vue from 'vue'
    import * as storage from '@/utils/storage'
    
    /*==================|-- * 只能输入正整数指令 * start --|==================*/
    // 使用方法: v-enter-number
    Vue.directive('enterNumber', {
      inserted: function (el) {
        el.addEventListener("keypress", function (e) {
          e = e || window.event;
          let charcode = typeof e.charCode == 'number' ? e.charCode : e.keyCode;
          let re = /\d/;
          if (!re.test(String.fromCharCode(charcode)) && charcode > 9 && !e.ctrlKey) {
            if (e.preventDefault) {
              e.preventDefault();
            } else {
              e.returnValue = false;
            }
          }
        });
    
        let legalContent, //开启输入法之前的输入内容
          LOCK = false; //是否开启中文输入法
        el.addEventListener('compositionstart', (e) => {
          legalContent = e.target.value; //保存中文输入法之前的内容
          LOCK = true; //加上锁
        }, false);
    
        el.addEventListener('compositionend', (e) => {
          e.target.value = legalContent;
          LOCK = false; // 解锁
        }, false);
    
        el.addEventListener('input', (e) => {
          if (!LOCK) {
            e.target.value = e.target.value.replace(/\D/, '');
          }
        }, false);
      },
      update: function (el) {
        el.addEventListener('paste', (e) => {
          e.preventDefault();
        }, false);
      }
    });
    /*==================|-- * 只能输入正整数指令 * end --|==================*/
    
    
    /*==================|-- * 只能输入正数(包含小数)指令 * start --|==================*/
    // 使用方法: v-enter-number-point
    Vue.directive('enterNumberPoint', {
      inserted: function (el) {
        // 用来处理中文输入法的情况  start
        let input = el.getElementsByTagName("input")[0]  //因为是用的el-input,所以这么拿到input
        input.setAttribute("type", "number"); //设置类型是number,解决输入中文的问题,尝试过很多种方法,但最终发现,只有设置为number可以解决
        input.setAttribute("step", "0.01"); //解决输入不了,如1.1这种的数据
        // 用来处理中文输入法的情况  end
    
    
        let isSelect = false
        el.addEventListener("keypress", function (e) {  //在控件有焦点的情况下按下键时发生
          e = e || window.event;
          let charcode = typeof e.charCode == 'number' ? e.charCode : e.keyCode;
          let re = /\d/;
          if (charcode == 46) {
            if (e.target.value && e.target.value.includes('.')) {
              e.preventDefault();
            }
          } else if (!re.test(String.fromCharCode(charcode)) && charcode > 9 && !e.ctrlKey) {
            if (e.preventDefault) {
              e.preventDefault();
            } else {
              e.returnValue = false;
            }
          } else {
            if (!isSelect) {  //处于截断时候的bug
              if (e.target.value && e.target.value.includes('.')) { //如果输入小数的时候
                let len = e.target.value.toString().split(".")[1].length;
                if (len === 2 || e.key === '.') {
                  e.preventDefault();
                }
              }
            }
          }
        });
    
        //失去焦点=>保留指定位小数
        el.addEventListener("keyup", e => {
          isSelect = false
          // console.log('keyup', e, e.target.value)
        }, false)
    
        //选中
        el.addEventListener("select", e => {
          isSelect = true
          // console.log('select', e, e.target.value)
        }, false)
    
        //点击
        el.addEventListener("click", e => {
          isSelect = false
          // console.log('click', e, e.target.value)
        }, false)
    
        //失去焦点
        el.addEventListener("focusout", e => {
          isSelect = true
          // console.log('focusout', e, e.target.value)
        }, false)
    
        let legalContent, //开启输入法之前的输入内容
          LOCK = false; //是否开启中文输入法
        el.addEventListener('compositionstart', (e) => {
          legalContent = e.target.value; //保存中文输入法之前的内容
          LOCK = true; //加上锁
          isSelect = true
        }, false);
    
        el.addEventListener('compositionend', (e) => {
          e.target.value = legalContent;
          LOCK = false; // 解锁
          isSelect = true
        }, false);
    
        el.addEventListener('input', (e) => {
          if (LOCK) return 0;
          if (!LOCK) {
            setInputVal(e)
          } else {
          }
        }, false);
    
        function setInputVal (e) {
          let dataLen = e.data ? e.data.length : 1
          let len = e.key ? 1 : dataLen
          if (e.target.value && e.target.value.includes('.')) { //如果输入小数的时候
            if (!/^([1-9]+\d*|0{1})\.\d{0,2}$/.test(e.target.value)) {
              e.target.value = e.target.value.slice(0, e.target.value.length - len)
            }
          } else {     //如果输入整数的时候
            if (!/^([1-9]+\d*|0{1})$/.test(e.target.value)) {
              e.target.value = e.target.value.slice(0, e.target.value.length - len)
            }
          }
        }
      },
      update: function (el) {
        el.addEventListener('paste', (e) => {
          console.log('paste')
          e.preventDefault();  //禁止复制,防止不知道复制到是什么东西
        }, false);
      }
    });
    /*==================|-- * 只能输入正数(包含小数)指令 * end --|==================*/
    
    
    /*==================|-- * 后台管理按钮权限指令 * start --|==================*/
    // 使用方法: v-has="`/table/Table_Update`"
    Vue.directive('has', {
      bind: function (el, binding) {
        if (!binding.value) {
          return el.style.display = 'none';
        }
        if (!Vue.prototype.$_has(binding.value)) {
          el.style.display = 'none';
        }
      }
    });
    //权限检查方法
    Vue.prototype.$_has = function (value) {
      let isExist = false;
      let perms = storage.get('perms') || []
      if (perms === undefined || perms === null || !perms) {
        return false;
      }
    
      for (let item of perms) {
        if (item && item.indexOf(value) > -1) {
          isExist = true;
          break;
        }
      }
      // console.log('权限', perms)
      return isExist;
    };
    /*==================|-- * 权限指令 * end --|==================*/
    
    

    监听触摸事件

    import vue from 'vue'
    
    /************* 事例 start **************
     <div class="box" 
         v-tap="(e)=>vueTouch('点击',e)" 
         v-longtap="(e)=>vueTouch('长按',e)" 
         v-swipeleft="(e)=>vueTouch('左滑',e)"
         v-swiperight="(e)=>vueTouch('右滑',e)"
         v-swipeup="(e)=>vueTouch('上滑',e)"
         v-swipedown="(e)=>vueTouch('下滑',e)"
      >{{ name }}</div>
    ************* 事例 end **************/
    
    function vueTouch(el, binding, type) {
      var _this = this;
      this.obj = el;
      this.binding = binding;
      this.touchType = type;
      this.vueTouches = {
        x: 0,
        y: 0
      };
      this.vueMoves = true;
      this.vueLeave = true;
      this.longTouch = true;
      this.vueCallBack = typeof (binding.value) == "object" ? binding.value.fn : binding.value;
      this.obj.addEventListener("touchstart", function (e) {
        _this.start(e);
      }, false);
      this.obj.addEventListener("touchend", function (e) {
        _this.end(e);
      }, false);
      this.obj.addEventListener("touchmove", function (e) {
        _this.move(e);
      }, false);
    };
    vueTouch.prototype = {
      start: function (e) {
        this.vueMoves = true;
        this.vueLeave = true;
        this.longTouch = true;
        this.vueTouches = {
          x: e.changedTouches[0].pageX,
          y: e.changedTouches[0].pageY
        };
        this.time = setTimeout(function () {
          if (this.vueLeave && this.vueMoves) {
            this.touchType == "longtap" && this.vueCallBack(this.binding.value, e);
            this.longTouch = false;
          };
        }.bind(this), 500);
      },
      end: function (e) {
        var disX = e.changedTouches[0].pageX - this.vueTouches.x;
        var disY = e.changedTouches[0].pageY - this.vueTouches.y;
        clearTimeout(this.time);
        if (Math.abs(disX) > 10 || Math.abs(disY) > 100) {
          this.touchType == "swipe" && this.vueCallBack(this.binding.value, e);
          if (Math.abs(disX) > Math.abs(disY)) {
            if (disX > 10) {
              this.touchType == "swiperight" && this.vueCallBack(this.binding.value, e);
            };
            if (disX < -10) {
              this.touchType == "swipeleft" && this.vueCallBack(this.binding.value, e);
            };
          } else {
            if (disY > 10) {
              this.touchType == "swipedown" && this.vueCallBack(this.binding.value, e);
            };
            if (disY < -10) {
              this.touchType == "swipeup" && this.vueCallBack(this.binding.value, e);
            };
          };
        } else {
          if (this.longTouch && this.vueMoves) {
            this.touchType == "tap" && this.vueCallBack(this.binding.value, e);
            this.vueLeave = false
          };
        };
      },
      move: function (e) {
        this.vueMoves = false;
      }
    };
    vue.directive("tap", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "tap");
      }
    });
    vue.directive("swipe", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "swipe");
      }
    });
    vue.directive("swipeleft", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "swipeleft");
      }
    });
    vue.directive("swiperight", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "swiperight");
      }
    });
    vue.directive("swipedown", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "swipedown");
      }
    });
    vue.directive("swipeup", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "swipeup");
      }
    });
    vue.directive("longtap", {
      bind: function (el, binding) {
        new vueTouch(el, binding, "longtap");
      }
    });
    
    // 自动聚焦
    vue.directive("focus", {
      inserted: function (el, value) {
        if (value) {
          console.log('自动聚焦')
          el.focus();
        }
      }
    });
    

    全局loading

    ///loading.less
    @keyframes custom-loading-rotate {
      from {
        transform: rotate(0deg);
      }
    
      to {
        transform: rotate(360deg);
      }
    }
    
    .custom-loading {
      width: 100%;
      height: 100%;
      position: fixed;
      left: 0;
      top: 0;
      z-index: 100;
      background-color: rgba(255, 255, 255, 0.5);
      overflow: hidden;
    }
    
    .custom-loading .custom-loading-round {
      width: 30px;
      height: 30px;
      border-radius: 50%;
      border: 4px solid #f9c653;
      border-left-color: transparent;
      animation: custom-loading-rotate 1s linear infinite;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      margin: auto;
    }
    
    import vue from 'vue'
    import '@/assets/loading.less'
    
    //使用方法: v-loading="isShowLoding"
    
    vue.directive('loading', {
      bind: (el, binding) => {
        const tempDiv = document.createElement('div')
        tempDiv.className = 'custom-loading'
        const round = document.createElement('div')
        round.className = 'custom-loading-round'
        tempDiv.appendChild(round)
        el.loadingElement = tempDiv
        const curStyle = window.getComputedStyle(el)
        const position = curStyle.position
        if (position === 'absolute' || position === 'relative') {
          el.style.position = position
        } else {
          el.style.position = 'relative'
        }
        if (binding.value) {
          el.appendChild(tempDiv)
        }
      },
      update: (el, binding) => {
        if (binding.value) {
          if (el.loadingElement.parentNode === null) {
            el.appendChild(el.loadingElement)
          }
        } else {
          if (el === el.loadingElement.parentNode) {
            el.removeChild(el.loadingElement)
          }
        }
      },
      unbind: (el) => {
        if (el.loadingElement.parentNode === el) {
          el.removeChild(el.loadingElement)
        }
        el.loadingElement = null
      }
    })
    

    相关文章

      网友评论

          本文标题:【前端之日常工作】常使用的自定义指令集合

          本文链接:https://www.haomeiwen.com/subject/prhbjctx.html