• vue自定义全局指令


    指令:

    Vue 自定义指令有全局注册和局部注册两种方式。先来看看注册全局指令的方式,通过 Vue.directive( id, [definition] ) 方式注册全局指令。然后在入口文件中进行 Vue.use() 调用。

    批量注册指令,新建 directives/index.js 文件

    import copy from './copy'
    import longpress from './longpress'
    // 自定义指令
    const directives = {
      copy,
      longpress,
    }
    
    export default {
      install(Vue) {
        Object.keys(directives).forEach((key) => {
          Vue.directive(key, directives[key])
        })
      },
    }
    

    在 main.js 引入并调用

    import Vue from 'vue'
    import Directives from './JS/directives'
    Vue.use(Directives)
    

    指令定义函数提供了几个钩子函数(可选):

    • bind: 只调用一次,指令第一次绑定到元素时调用,可以定义一个在绑定时执行一次的初始化动作。
    • inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
    • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值。
    • componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
    • unbind: 只调用一次, 指令与元素解绑时调用。

    v-LazyLoad 图片懒加载

    背景:在类电商类项目,往往存在大量的图片,如 banner 广告图,菜单导航图,美团等商家列表头图等。图片众多以及图片体积过大往往会影响页面加载速度,造成不良的用户体验,所以进行图片懒加载优化势在必行。

    需求:实现一个图片懒加载指令,只加载浏览器可见区域的图片。

    思路:

    1. 图片懒加载的原理主要是判断当前图片是否到了可视区域这一核心逻辑实现的
    2. 拿到所有的图片 Dom ,遍历每个图片判断当前图片是否到了可视区范围内
    3. 如果到了就设置图片的 src 属性,否则显示默认图片

    图片懒加载有两种方式可以实现,一是绑定 srcoll 事件进行监听,二是使用 IntersectionObserver 判断图片是否到了可视区域,但是有浏览器兼容性问题。

    下面封装一个懒加载指令兼容两种方法,判断浏览器是否支持 IntersectionObserver API,如果支持就使用 IntersectionObserver 实现懒加载,否则则使用 srcoll 事件监听 + 节流的方法实现。

    const LazyLoad = {
      // install方法
      install(Vue, options) {
        const defaultSrc = options.default
        Vue.directive('lazy', {
          bind(el, binding) {
            LazyLoad.init(el, binding.value, defaultSrc)
          },
          inserted(el) {
            if (IntersectionObserver) {
              LazyLoad.observe(el)
            } else {
              LazyLoad.listenerScroll(el)
            }
          },
        })
      },
      // 初始化
      init(el, val, def) {
        el.setAttribute('data-src', val)
        el.setAttribute('src', def)
      },
      // 利用IntersectionObserver监听el
      observe(el) {
        var io = new IntersectionObserver((entries) => {
          const realSrc = el.dataset.src
          if (entries[0].isIntersecting) {
            if (realSrc) {
              el.src = realSrc
              el.removeAttribute('data-src')
            }
          }
        })
        io.observe(el)
      },
      // 监听scroll事件
      listenerScroll(el) {
        const handler = LazyLoad.throttle(LazyLoad.load, 300)
        LazyLoad.load(el)
        window.addEventListener('scroll', () => {
          handler(el)
        })
      },
      // 加载真实图片
      load(el) {
        const windowHeight = document.documentElement.clientHeight
        const elTop = el.getBoundingClientRect().top
        const elBtm = el.getBoundingClientRect().bottom
        const realSrc = el.dataset.src
        if (elTop - windowHeight < 0 && elBtm > 0) {
          if (realSrc) {
            el.src = realSrc
            el.removeAttribute('data-src')
          }
        }
      },
      // 节流
      throttle(fn, delay) {
        let timer
        let prevTime
        return function (...args) {
          const currTime = Date.now()
          const context = this
          if (!prevTime) prevTime = currTime
          clearTimeout(timer)
    
          if (currTime - prevTime > delay) {
            prevTime = currTime
            fn.apply(context, args)
            clearTimeout(timer)
            return
          }
    
          timer = setTimeout(function () {
            prevTime = Date.now()
            timer = null
            fn.apply(context, args)
          }, delay)
        }
      },
    }
    
    export default LazyLoad

    使用,将组件内 标签的 src 换成 v-LazyLoad

    <img v-LazyLoad="xxx.jpg" />

     

    v-permission  权限验证

    背景:在一些后台管理系统,我们可能需要根据用户角色进行一些操作权限的判断,很多时候我们都是粗暴地给一个元素添加 v-if / v-show 来进行显示隐藏,但如果判断条件繁琐且多个地方需要判断,这种方式的代码不仅不优雅而且冗余。针对这种情况,我们可以通过全局自定义指令来处理。

    需求:自定义一个权限指令,对需要权限判断的 Dom 进行显示隐藏。

    思路:

      1. 自定义一个权限数组
      2. 判断用户的权限是否在这个数组内,如果是则显示,否则则移除 Dom
    function checkArray(key) {
      let arr = ['1', '2', '3', '4']
      let index = arr.indexOf(key)
      if (index > -1) {
        return true // 有权限
      } else {
        return false // 无权限
      }
    }
    
    const permission = {
      inserted: function (el, binding) {
        let permission = binding.value // 获取到 v-permission的值
        if (permission) {
          let hasPermission = checkArray(permission)
          if (!hasPermission) {
            // 没有权限 移除Dom元素
            el.parentNode && el.parentNode.removeChild(el)
          }
        }
      },
    }
    
    export default permission
    

    使用:给 v-permission 赋值判断即可

    <div class="btns">
      <!-- 显示 -->
      <button v-permission="'1'">权限按钮1</button>
      <!-- 不显示 -->
      <button v-permission="'10'">权限按钮2</button>
    </div>
    

      

    v-draggable 拖拽指令

    需求:实现一个拖拽指令,可在页面可视区域任意拖拽元素。

    思路:

    1. 设置需要拖拽的元素为相对定位,其父元素为绝对定位。
    2. 鼠标按下(onmousedown)时记录目标元素当前的 left 和 top 值。
    3. 鼠标移动(onmousemove)时计算每次移动的横向距离和纵向距离的变化值,并改变元素的 left 和 top 值
    4. 鼠标松开(onmouseup)时完成一次拖拽
     
    const draggable = {
      inserted: function (el) {
        el.style.cursor = 'move'
        el.onmousedown = function (e) {
          let disx = e.pageX - el.offsetLeft
          let disy = e.pageY - el.offsetTop
          document.onmousemove = function (e) {
            let x = e.pageX - disx
            let y = e.pageY - disy
            let maxX = document.body.clientWidth - parseInt(window.getComputedStyle(el).width)
            let maxY = document.body.clientHeight - parseInt(window.getComputedStyle(el).height)
            if (x < 0) {
              x = 0
            } else if (x > maxX) {
              x = maxX
            }
    
            if (y < 0) {
              y = 0
            } else if (y > maxY) {
              y = maxY
            }
    
            el.style.left = x + 'px'
            el.style.top = y + 'px'
          }
          document.onmouseup = function () {
            document.onmousemove = document.onmouseup = null
          }
        }
      },
    }
    export default draggable

    <template>
      <div class="el-dialog" v-draggable></div>
    </template>

      

     

      

      

  • 相关阅读:
    git查看某个文件的提交记录
    git修改文件夹名字
    Visual Studio 2013 在使用 razor无智能提示的解决办法
    git部分提交
    SQL SERVER与C#的数据类型对应表
    使用VBS实现SSH远程登录并自动执行命令
    安装并配置Samba
    Trouble and solution
    两台电脑间共享文件
    Astah类图中使用list<>
  • 原文地址:https://www.cnblogs.com/webljl/p/14171790.html
Copyright © 2020-2023  润新知