Home > Web Front-end > Vue.js > body text

4 custom instructions worth knowing about in vue (practical sharing)

青灯夜游
Release: 2021-12-15 19:37:26
forward
2086 people have browsed it

In addition to the default core directives (v-model and v-show), Vue also allows the registration of custom directives. This article will share with you four practical vue custom instructions. I hope it will be helpful to you.

4 custom instructions worth knowing about in vue (practical sharing)

Four practical vue custom instructions

1, v-drag

Requirement: mouse drag element

Idea:

  • Element offset = mouse sliding The coordinates after - the coordinates when the mouse initially clicks on the element. The distance between the element and the top and left of the visible area when the initial click is made.
  • Use the visible area as the boundary and limit dragging within the visible area. [Related recommendations: "vue.js Tutorial"]

    Code:

    Vue.directive('drag', {
      inserted(el) {
        let header = el.querySelector('.dialog_header')
        header.style.cssText += ';cursor:move;'
        header.onmousedown = function (e) {
          //获取当前可视区域宽、高
          let clientWidth = document.documentElement.clientWidth
          let clientHeight = document.documentElement.clientHeight
    
          //获取自身宽高
          let elWidth = el.getBoundingClientRect().width
          let elHeight = el.getBoundingClientRect().height
    
          //获取当前距离可视区域的top、left
          let elTop = el.getBoundingClientRect().top
          let elLeft = el.getBoundingClientRect().left
    
          //获取点击时候的坐标
          let startX = e.pageX
          let startY = e.pageY
    
          document.onmousemove = function (e) {
            //元素偏移量 = 鼠标滑动后的坐标 - 鼠标初始点击元素时的坐标 + 初始点击时元素距离可视区域的top、left
            let moveX = e.pageX - startX + elLeft
            let moveY = e.pageY - startY + elTop
    
            //将可视区域作为边界,限制在可视区域里面拖拽
            if ((moveX + elWidth) > clientWidth || moveX < 0 || (moveY + elHeight) > clientHeight || moveY < 0) {
              return
            }
    
            el.style.cssText += &#39;top:&#39; + moveY + &#39;px;left:&#39; + moveX + &#39;px;&#39;
          }
          document.onmouseup = function () {
            document.onmousemove = null
            document.onmouseup = null
          }
        }
      }
    })
    Copy after login

    ##2, v-wordlimit

    Requirements: The background field limits the length and distinguishes between Chinese and English, two bytes for Chinese and one byte for English; Therefore, the input box needs to limit the number of words entered and distinguish the number of bytes, and it needs to echo the number of words entered.

    Idea:

      One byte regular/[\x00-\xff]/g
    • Create an element that wraps the word limit, and position the layout in textarea and On the input box,
    • respectively calculates the input characters for one byte, enLen, and two bytes, cnLen; used for subsequent string truncation processing
    • When the number of input characters exceeds the limit The number of words, truncation processing; substr(0,enLen cnLen)
    • The interface updates the value of the input box, or initializes the value of the input box, and needs to echo the correct number of bytes
    Code:

    Vue.directive(&#39;wordlimit&#39;,{
      bind(el,binding){
        console.log(&#39;bind&#39;);
        let { value } = binding
        Vue.nextTick(() =>{
          //找到输入框是textarea框还是input框
          let current = 0
          let arr = Array.prototype.slice.call(el.children)
          for (let i = 0; i < arr.length; i++) {
            if(arr[i].tagName==&#39;TEXTAREA&#39; || arr[i].tagName==&#39;INPUT&#39;){
              current = i
            }
          }
      
          //更新当前输入框的字节数
          el.children[el.children.length-1].innerHTML = el.children[current].value.replace(/[^\x00-\xff]/g,&#39;**&#39;).length +&#39;/&#39;+value//eslint-disable-line
        })
      },
      update(el,binding){
        console.log(&#39;update&#39;);
        let { value } = binding
        Vue.nextTick(() =>{
          //找到输入框是textarea框还是input框
          let current = 0
          let arr = Array.prototype.slice.call(el.children)
          for (let i = 0; i < arr.length; i++) {
            if(arr[i].tagName==&#39;TEXTAREA&#39; || arr[i].tagName==&#39;INPUT&#39;){
              current = i
            }
          }
      
          //更新当前输入框的字节数
          el.children[el.children.length-1].innerHTML = el.children[current].value.replace(/[^\x00-\xff]/g,&#39;**&#39;).length +&#39;/&#39;+value//eslint-disable-line
        })
      },
      inserted(el,binding){
        console.log(&#39;inserted&#39;);
        let { value } = binding
    
        //找到输入框是textarea框还是input框
        let current = 0
        let arr = Array.prototype.slice.call(el.children)
        for (let i = 0; i < arr.length; i++) {
          if(arr[i].tagName==&#39;TEXTAREA&#39; || arr[i].tagName==&#39;INPUT&#39;){
            current = i
          }
        }
    
        //创建包裹字数限制的元素,并定位布局在textarea和input框上
        let div = document.createElement(&#39;div&#39;)
        if(el.children[current].tagName==&#39;TEXTAREA&#39;){//是textarea,定位在右下角
          div.style = &#39;color:#909399;position:absolute;font-size:12px;bottom:5px;right:10px;&#39;
        }else{
          let styStr = &#39;&#39;
          if(!el.classList.contains(&#39;is-disabled&#39;)){//input框不是置灰的状态则添加背景颜色
            styStr = &#39;background:#fff;&#39;
          }
          div.style = &#39;color:#909399;position:absolute;font-size:12px;bottom:2px;right:10px;line-height:28px;height:28px;&#39;+styStr
        }
    
        div.innerHTML = &#39;0/&#39;+ value
        el.appendChild(div)
        el.children[current].style.paddingRight = &#39;60px&#39;
    
        el.oninput = () =>{
          let val = el.children[current].value
          val = val.replace(/[^\x00-\xff]/g,&#39;**&#39;) //eslint-disable-line
          // 字数限制的盒子插入到el后是最后一个元素
          el.children[el.children.length-1].innerHTML = val.length + &#39;/&#39; + value
          if(val.length>value){
            let cnLen = 0 //一个字节的字数
            let enLen = 0 //两个字节的字数
    
            if(val.match(/[^**]/g) && val.match(/[^**]/g).length){
              enLen = val.match(/[^**]/g).length // 计算一个字节的字数
    
              //一个字节两个字节都有的情况
              if((value - val.match(/[^**]/g).length)>0){
                cnLen = Math.floor((value - val.match(/[^**]/g).length)/2)
              }else{
                cnLen = 0
              }
            }else{ //全部两个字节的情况
              enLen = 0
              cnLen = Math.floor(value/2)
            }
    
            if(enLen>value){
              enLen = value
            }
    
            //超过限定字节数则截取
            el.children[current].value = el.children[current].value.substr(0,enLen+cnLen)
    
            //更新当前输入框的字节数
            el.children[el.children.length-1].innerHTML = el.children[current].value.replace(/[^\x00-\xff]/g,&#39;**&#39;).length +&#39;/&#39;+value//eslint-disable-line
    
          }
        }
    
      },
    })
    Copy after login

    Use:

    <el-input type="textarea" rows="3" v-wordlimit="20" v-model="value"></el-input>
    Copy after login

    3、v-anthor

    Requirements: Click on an element (usually a title, subtitle, etc.), and the animation will scroll to the corresponding content block

    Idea:

      The timer uses window. scrollBy
    • If you do not consider ie, you can directly use window.scrollBy({ top: ,left:0,behavior:'smooth' })
    Code:

    Vue.directive(&#39;anchor&#39;,{
      inserted(el,binding){
        let { value } = binding
        let timer = null
        el.addEventListener(&#39;click&#39;,function(){
          // 当前元素距离可视区域顶部的距离
          let currentTop = el.getBoundingClientRect().top
          animateScroll(currentTop)
        },false)
        
        function animateScroll(currentTop){
          if(timer){
            clearInterval(timer)
          }
          let c = 9
          timer = setInterval(() =>{
            if(c==0){
              clearInterval(timer)
            }
            c--
            window.scrollBy(0,(currentTop-value)/10)
          },16.7)
        }
    
      }
    })
    Copy after login

    Use:

    <div class="box" v-anchor="20" style="color:red;">是的</div>
    Copy after login

    4, v-hasRole##Requirements: According to the system Add or delete corresponding elements to the role

    Code:

    Vue.directive(&#39;hasRole&#39;,{
      inserted(el,binding){
        let { value } = binding
        let roles = JSON.parse(sessionStorage.getItem(&#39;userInfo&#39;)).roleIds
    
        if(value && value instanceof Array && value.length>0){
    
          let hasPermission = value.includes(roles)
    
          if(!hasPermission){
            el.parentNode && el.parentNode.removeChild(el)
          }
        }else{
          throw new Error(`请检查指令绑定的表达式,正确格式例如 v-hasRole="[&#39;admin&#39;,&#39;reviewer&#39;]"`)
        }
      }
    })
    Copy after login

    For more programming-related knowledge, please visit:

    Introduction to Programming

    ! !

    The above is the detailed content of 4 custom instructions worth knowing about in vue (practical sharing). For more information, please follow other related articles on the PHP Chinese website!

    Related labels:
    source:juejin.cn
    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
    Popular Tutorials
    More>
    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template
    About us Disclaimer Sitemap
    php.cn:Public welfare online PHP training,Help PHP learners grow quickly!