vue2.x 常用自定义指令,项目常用自定义指令

directives.js

import Vue from 'vue'

/**
 * 点击元素外 触发事件
 * 
 */
Vue.directive('clickoutside', {
  bind(el, binding, vnode) {
    function documentHandler(e) {
      // 这里判断点击的元素是否是本身,是本身,则返回
      if (el.contains(e.target)) {
        return false
      }
      // 判断指令中是否绑定了函数
      if (binding.expression) {
        // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
        binding.value(e)
      }
    }
    // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
    el.__vueClickOutside__ = documentHandler
    document.addEventListener('click', documentHandler)
  },
  update() { },
  unbind(el, binding) {
    // 解除事件监听
    document.removeEventListener('click', el.__vueClickOutside__)
    delete el.__vueClickOutside__
  }
})
/* 
*响应缩放指令 v-resize
*使用该指令可以响应元素宽高改变时执行的方法。
*示例:<div v-resize="resize"></div> 
*methods:{
  resize(){

  }
}
*/
Vue.directive('resize', {
  // 指令的名称
  bind(el, binding) {
    // el为绑定的元素,binding为绑定给指令的对象
    let width = "",
      height = "";

    function isReize() {
      const style = document.defaultView.getComputedStyle(el);
      if (width !== style.width || height !== style.height) {
        binding.value(); // 关键
      }
      width = style.width;
      height = style.height;
    }
    el.__vueSetInterval__ = setInterval(isReize, 300);
  },
  unbind(el) {
    clearInterval(el.__vueSetInterval__);
  }
})


/* 
 *文本内容复制指令 v-copy
 *使用该指令可以复制元素的文本内容(指令支持单击复制 v-copy、双击复制 v-copy.dblclick、点击icon复制 v-copy.icon 三种模式),不传参数时,默认使用单击复制
 *示例:<div v-copy> 单击复制 </div> <div v-copy.dblclick> 双击复制 </div> <div v-copy.icon> icon复制 </div>
 */

function copyHandleClick(text) {
  // 创建元素
  if (!document.getElementById('copyTarget')) {
    const copyTarget = document.createElement('input')
    copyTarget.setAttribute('style', 'position:fixed;top:0;left:0;opacity:0;z-index:-1000;')
    copyTarget.setAttribute('id', 'copyTarget')
    document.body.appendChild(copyTarget)
  }
  // 复制内容
  const input = document.getElementById('copyTarget')
  input.value = text
  input.select()
  document.execCommand('copy')
  // alert('复制成功')
}
Vue.directive('copy', {
  bind(el, binding) {
    // 双击触发复制
    if (binding.modifiers.dblclick) {
      el.addEventListener('dblclick', () => copyHandleClick(el.innerText))
      el.style.cursor = 'copy'
    }
    // 点击icon触发复制
    else if (binding.modifiers.icon) {
      if (el.hasIcon) return
      const iconElement = document.createElement('i')
      iconElement.setAttribute('class', 'el-icon-document-copy')
      iconElement.setAttribute('style', 'margin-left:5px')
      el.appendChild(iconElement)
      el.hasIcon = true
      iconElement.addEventListener('click', () => copyHandleClick(el.innerText))
      iconElement.style.cursor = 'copy'
    }
    // 单击触发复制
    else {
      el.addEventListener('click', () => copyHandleClick(el.innerText))
      el.style.cursor = 'copy'
    }
  }
})


/* 
 *元素全屏指令 v-screenfull
 *全屏指令,点击元素进行全屏/退出全屏的操作。支持元素后面是否插入 element-ui 的全屏图标 el-icon-full-screen。
 *示例:<div v-screenfull.icon> 全屏 </div>
 *Fullscreen an element <div id='fullId'>text</div> <div v-screenfull.icon="'fullId'"> 全屏 </div>
 *需要安装插件 npm install screenfull
 */
import screenfull from 'screenfull'

function screenfullClick(dom) {
  if (!screenfull.isEnabled) {
    alert('浏览器不支持全屏')
    return
  }
  let element = document.getElementById(dom);
  screenfull.toggle(element)
}

Vue.directive('screenfull', {
  bind(el, binding) {
    if (binding.modifiers.icon) {
      if (el.hasIcon) return
      // 创建全屏图标
      const iconElement = document.createElement('i')
      iconElement.setAttribute('class', 'el-icon-full-screen')
      iconElement.setAttribute('style', 'margin-left:5px')
      el.appendChild(iconElement)
      el.hasIcon = true
    }
    el.style.cursor = el.style.cursor || 'pointer'
    // 监听点击全屏事件
    el.addEventListener('click', () => screenfullClick(binding.value))
  }
})

/* 
 *文字超出省略指令 v-ellipsis
 *使用该指令当文字内容超出宽度(默认 100% )时自动变为省略形式
 *示例:<div v-ellipsis> 需要省略的文字xxxxxxxxxxxx副本</div>
 */
Vue.directive('ellipsis', {
  bind(el, binding) {
    if (binding.arg) {
      el.style.width = binding.arg + 'px'
    } else {
      el.style.width = '100%'
    }

    el.style.whiteSpace = 'nowrap'
    el.style.overflow = 'hidden';
    el.style.textOverflow = 'ellipsis';
  }
})


/* 
 *字符串整形指令 v-format
 *使用该指令可以修改字符串,如使用 v-format.toFixed 保留两位小数、 v-format.price 将内容变成金额(每三位逗号分隔),可以同时使用,如 v-format.toFixed.price。
 *示例:例如将数字 243112.331 变成 243112.33,或 243,112.33。
 * <div v-format.toFixed.price="123333"></div>   显示结果123,333.00
 */
function formatNumber(num) {
  num += '';
  let strs = num.split('.');
  let x1 = strs[0];
  let x2 = strs.length > 1 ? '.' + strs[1] : '';
  var rgx = /(\d+)(\d{3})/;
  while (rgx.test(x1)) {
    x1 = x1.replace(rgx, '$1' + ',' + '$2');
  }
  return x1 + x2
}
Vue.directive('format', {
  bind(el, binding, vnode) {
    const {
      value,
      modifiers
    } = binding
    if (!value) return
    let formatValue = value
    if (modifiers.toFixed) {
      formatValue = value.toFixed(2)
    }
    console.log(formatValue)
    if (modifiers.price) {
      formatValue = formatNumber(formatValue)
    }
    el.innerText = formatValue
  },
})


/* 
*主要适配 智慧渔港拖动
*自定义弹框拖拽
*v-defDialogDrag:{defDialogDrag}="obj"
* obj = {
    dialogDrag: true, //是否可拖动
    dragViewArea:"#main-body",//拖动可视区域
    dragFocusDom:".def-header" //鼠标可拖拽区域
}
*以left为基准
*/
Vue.directive('defDialogDrag', {
  bind(el, binding, vnode, oldVnode) {
    // console.log('binding::', binding.value)
    // 自定义属性,判断是否可拖拽 
    if (!binding.value.dialogDrag) return
    const dialogHeaderEl = el.querySelector(binding.value.dragFocusDom) //.drag-dialog-box
    const dragDom = el
    dialogHeaderEl.style.cssText += ';cursor:move;'
    dragDom.style.cssText += ';top:40px;'

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = (function () {
      if (document.body.currentStyle) {
        // 在ie下兼容写法
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {

      const viewArea = document.querySelector(binding.value.dragViewArea) //可视区拖动范围
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop
      // 获取可视范围padding
      let viewPl = Number(sty(viewArea, 'padding-left').substring(0, sty(viewArea, 'padding-left').length - 2)) || 0
      let viewPr = Number(sty(viewArea, 'padding-right').substring(0, sty(viewArea, 'padding-right').length - 2)) || 0
      let viewPt = Number(sty(viewArea, 'padding-top').substring(0, sty(viewArea, 'padding-top').length - 2)) || 0
      let viewPb = Number(sty(viewArea, 'padding-bottom').substring(0, sty(viewArea, 'padding-bottom').length - 2)) || 0

      console.log("wonendie", viewPl, viewPr, viewPt)

      const screenWidth = viewArea.clientWidth - viewPl - viewPr // 拖拽文本可视当前宽度
      const screenHeight = viewArea.clientHeight - viewPt - viewPb // 拖拽文本可视当前高度

      const dragDomWidth = dragDom.offsetWidth // 对话框宽度
      const dragDomheight = dragDom.offsetHeight // 对话框高度

      const minDragDomLeft = dragDom.offsetLeft - viewPl //拖拽最小left
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth + viewPl //拖拽最大left

      const minDragDomTop = dragDom.offsetTop - viewPt //拖拽最小top
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight //拖拽最大top

      // 获取到的值带px 正则匹配替换
      let styL = sty(dragDom, 'left')
      // 为兼容ie 
      if (styL === 'auto') styL = '0px'
      let styT = sty(dragDom, 'top')

      // console.log(styL)
      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100)
        styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100)
      } else {
        styL = +styL.replace(/px/g, '')
        styT = +styT.replace(/px/g, '')
      };

      document.onmousemove = function (e) {
        // 通过事件委托,计算移动的距离
        let left = e.clientX - disX
        let top = e.clientY - disY

        // 边界处理
        if (-(left) > minDragDomLeft) {
          left = -(minDragDomLeft)
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {
          top = -(minDragDomTop)
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop
        }
        console.log(`移动的元素:left:${left + styL}px;top:${top + styT}px;`)
        // 移动当前元素
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`

        // emit onDrag event
        // vnode.child.$emit('dragDialog')
      }

      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
      return false
    }
  }
})

/* 
*主要适配 智慧渔港拖动
*自定义弹框拖拽
*v-rightDialogDrag:{rightDialogDrag}="obj"
* obj = {
    dialogDrag: true, //是否可拖动
    dragViewArea:"#main-body",//拖动可视区域
    dragFocusDom:".def-header" //鼠标可拖拽区域
}
*以right为基准
*/
Vue.directive('rightDialogDrag', {
  bind(el, binding, vnode, oldVnode) {
    // console.log('binding::', binding.value)
    // 自定义属性,判断是否可拖拽 
    if (!binding.value.dialogDrag) return
    const dialogHeaderEl = el.querySelector(binding.value.dragFocusDom) //.drag-dialog-box
    const dragDom = el
    dialogHeaderEl.style.cssText += ';cursor:move;'
    dragDom.style.cssText += ';top:40px;'

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = (function () {
      if (document.body.currentStyle) {
        // 在ie下兼容写法
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {

      const viewArea = document.querySelector(binding.value.dragViewArea) //可视区拖动范围
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop
      // 获取可视范围padding
      let viewPl = Number(sty(viewArea, 'padding-left').substring(0, sty(viewArea, 'padding-left').length - 2)) || 0
      let viewPr = Number(sty(viewArea, 'padding-right').substring(0, sty(viewArea, 'padding-right').length - 2)) || 0
      let viewPt = Number(sty(viewArea, 'padding-top').substring(0, sty(viewArea, 'padding-top').length - 2)) || 0
      let viewPb = Number(sty(viewArea, 'padding-bottom').substring(0, sty(viewArea, 'padding-bottom').length - 2)) || 0

      console.log("wonendie", viewPl, viewPr, viewPt)

      const screenWidth = viewArea.clientWidth - viewPl - viewPr // 拖拽文本可视当前宽度
      const screenHeight = viewArea.clientHeight - viewPt - viewPb // 拖拽文本可视当前高度

      const dragDomWidth = dragDom.offsetWidth // 对话框宽度
      const dragDomheight = dragDom.offsetHeight // 对话框高度

      const minDragDomLeft = dragDom.offsetLeft + viewPl
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth - viewPl

      const minDragDomTop = dragDom.offsetTop - viewPt //拖拽最小top
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight //拖拽最大top

      // 获取到的值带px 正则匹配替换
      let styL = sty(dragDom, 'left')
      // 为兼容ie 
      if (styL === 'auto') styL = '0px'
      let styT = sty(dragDom, 'top')

      // console.log(styL)
      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100)
        styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100)
      } else {
        styL = +styL.replace(/px/g, '')
        styT = +styT.replace(/px/g, '')
      };

      document.onmousemove = function (e) {
        // 通过事件委托,计算移动的距离
        let left = e.clientX - disX
        let top = e.clientY - disY

        // 边界处理
        if (-(left) > minDragDomLeft) {
          left = -(minDragDomLeft)
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {
          top = -(minDragDomTop)
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop
        }
        let right = screenWidth - dragDomWidth - left - styL
        // console.log(`移动的元素:right:${right}px;top:${top + styT}px;`)
        // 移动当前元素
        dragDom.style.cssText += `;right:${right}px;top:${top + styT}px;`

        // emit onDrag event
        // vnode.child.$emit('dragDialog')
      }

      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
      return false
    }
  }
})

/* binding v-dialogStretchdialogStretch:="{}"
value:{
  value:boolean是否可拉伸 (必传)
  minw:Number最小宽 (必传)
  maxw:Number最大宽 (必传)
  minh:Number最小高 (必传)
  maxh:Number 最大高 (必传)
  ratio:Number宽高比 (非必传)
}
*****
* pointer-events: none;通过对iframe限制 鼠标指针事件 禁止iframe影响拖拽 鼠标释放
*/
Vue.directive('dialogStretch', {
  bind(el, binding, vnode, oldVnode) {
    // 自定义属性,判断是否可拉伸
    const bindVal = binding.value
    if (!bindVal.value) return
    const dragDom = el
    // 在弹出框的右下角添加可拉伸标志 class='mouse'
    let dragMouse = dragDom.querySelector('.mouse')
    // 鼠标拖拽
    dragMouse.onmousedown = (e) => {
      // content区域
      const content = dragDom.parentNode.parentNode
      const contentW = content.offsetWidth
      const contentH = content.offsetHeight

      const disX = e.clientX
      const disY = e.clientY
      let initialW = dragDom.offsetWidth
      let initialH = dragDom.offsetHeight
      let iframeDom = document.getElementById("iframe_gis")

      document.onmousemove = function (e) {
        e.preventDefault() // 移动时禁用默认事件

        iframeDom.style.pointerEvents = "none"
        console.log("iframe元素", iframeDom)

        // 通过事件委托,计算移动的距离
        let Cwidth = disX - e.clientX + initialW
        let Cheight = e.clientY - disY + initialH


        // 距离底部20px停止拖动
        if (e.clientY > contentH - 40) {
          console.log("不能再拖了")
          return
        } else {
          if (!!bindVal.ratio) {
            // 设置比例 宽高等比缩放
            let width = Cheight / bindVal.ratio
            if (Cheight < (contentH - 40) && Cheight >= bindVal.minH && width < (contentW - 40)) {
              dragDom.style.width = `${width}px`
              dragDom.style.height = `${Cheight}px`
            }
          } else {
            // console.log("点击角坐标2",Cheight < contentH, Cheight,Cwidth < (contentW - 40),Cwidth >= bindVal.minW)
            if (Cheight < contentH && Cheight >= bindVal.minH && Cwidth < (contentW - 40) && Cwidth >= bindVal.minW) {
              // console.log("点击角坐标2", e.clientX, Cwidth)
              dragDom.style.width = `${Cwidth}px`
              dragDom.style.height = `${Cheight}px`
            }
          }
        }
      }
      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
        iframeDom.style.pointerEvents = "auto"
      }
      return false
    }
  }
})

/* binding
value:{
    value:boolean是否可拉伸 (必传)
    minw:Number最小宽 (必传)
    maxw:Number最大宽 (必传)
    minh:Number最小高 (必传)
    maxh:Number 最大高 (必传)
    ratio:Number宽高比 (非必传)
    ratio?
    minw:Number最小宽 (必传)
    maxw:Number最大宽 (必传)
    minh:Number最小高 (非必传)
    maxh:Number 最大高 (非必传)
 } */
Vue.directive('newDialogChange', {
  bind(el, binding, vnode, oldVnode) {
    // 自定义属性,判断是否可拉伸
    const bindVal = binding.value
    // console.log(bindVal, "binding")

    if (!bindVal.value) return
    const dragDom = el
    console.log(dragDom.childNodes[1].childNodes, "拖拽属性")
    // 在弹出框的右下角添加可拉伸标志 class='mouse'
    let dragMouse = dragDom.querySelector('.mouse')

    // 鼠标拖拽
    dragMouse.onmousedown = (e) => {
      // content区域
      const content = dragDom.parentNode.parentNode
      // console.log(content, "llllllllllllllllllllllllllllllll")
      const disX = e.clientX - dragDom.offsetWidth
      const disY = e.clientY - dragDom.offsetHeight



      document.onmousemove = function (e) {
        e.preventDefault() // 移动时禁用默认事件
        // 通过事件委托,计算移动的距离

        let width = e.clientX - disX
        let height = e.clientY - disY
        // console.log(e.clientX, e.clientY, content.offsetWidth, content.offsetHeight, width, height, 'sssss')

        // 距离底部20px停止拖动
        if (e.clientY > content.offsetHeight - 20) {
          // console.log("不能再拖了")
          return
        } else {
          if (!!bindVal.ratio) {
            // 设置比例 宽高等比缩放

            if (width < content.offsetWidth && height < content.offsetHeight) {
              if (!!bindVal.minw && bindVal.minw < width && !!bindVal.maxw && width < bindVal.maxw) {
                dragDom.style.width = `${width}px`
                dragDom.style.height = `${width * bindVal.ratio}px`
                // vnode.child.$emit('dragDialogHeight',width * bindVal.ratio)
              }
              // dragDom.style.height = `${width*0.6}px`
              // dragDom.style.height = `${height}px`
            }
          } else {
            // 不设置比例 宽高随意拖动
            if (width > content.offsetWidth && height < content.offsetHeight) {
              if (!!bindVal.minh && bindVal.minh < height && !!bindVal.maxh && height < bindVal.maxh) {
                dragDom.style.height = `${height}px`
              }
            } else if (width < content.offsetWidth && height > content.offsetHeight) {
              if (!!bindVal.minw && bindVal.minw < width && !!bindVal.maxw && width < bindVal.maxw) {
                dragDom.style.width = `${width}px`
              }
            } else if (width < content.offsetWidth && height < content.offsetHeight) {
              if (!!bindVal.minh && bindVal.minh < height && !!bindVal.maxh && height < bindVal.maxh) {
                dragDom.style.height = `${height}px`
              }
              if (!!bindVal.minw && bindVal.minw < width && !!bindVal.maxw && width < bindVal.maxw) {
                dragDom.style.width = `${width}px`
              }
              // dragDom.style.height = `${width*0.6}px`
              // dragDom.style.height = `${height}px`
            }
          }
        }




      }
      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
      return false
    }


  }
})


// v-dialogDrag: 弹窗拖拽属性
Vue.directive('newDialogDrag', {
  bind(el, binding, vnode, oldVnode) {
    // console.log('binding::',binding.value)
    // 自定义属性,判断是否可拖拽 
    if (!binding.value) return
    const dialogHeaderEl = el.querySelector('.drag-fouce-box') //.drag-dialog-box
    const dragDom = el
    // console.log("44444444444",dialogHeaderEl)
    dialogHeaderEl.style.cssText += ';cursor:move;'
    dragDom.style.cssText += ';top:40px;'

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = (function () {
      if (document.body.currentStyle) {
        // 在ie下兼容写法
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {
      console.log(e)
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop

      const screenWidth = document.body.clientWidth // body当前宽度
      const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取)

      const dragDomWidth = dragDom.offsetWidth // 对话框宽度
      const dragDomheight = dragDom.offsetHeight // 对话框高度

      const minDragDomLeft = dragDom.offsetLeft
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

      const minDragDomTop = dragDom.offsetTop
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight

      // 获取到的值带px 正则匹配替换
      let styL = sty(dragDom, 'left')
      // 为兼容ie 
      if (styL === 'auto') styL = '0px'
      let styT = sty(dragDom, 'top')

      // console.log(styL)
      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100)
        styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100)
      } else {
        styL = +styL.replace(/px/g, '')
        styT = +styT.replace(/px/g, '')
      };

      document.onmousemove = function (e) {
        // 通过事件委托,计算移动的距离
        let left = e.clientX - disX
        let top = e.clientY - disY
        // 边界处理
        if (-(left) > minDragDomLeft) {
          left = -(minDragDomLeft)
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {
          top = -(minDragDomTop)
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop
        }

        // 移动当前元素
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`

        // emit onDrag event
        // vnode.child.$emit('dragDialog')
      }

      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
      return false
    }
  }
})






// 适配可视范围拖动
Vue.directive('priviewDrag', {
  bind(el, binding, vnode, oldVnode) {
    // 自定义属性,判断是否可拖拽 
    if (!binding.value) return
    const dialogHeaderEl = el.querySelector('.model-move') //.drag-dialog-box
    const dragDom = el
    // console.log("44444444444",dialogHeaderEl)
    dialogHeaderEl.style.cssText += ';cursor:move;'
    dragDom.style.cssText += ';top:40px;'

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = (function () {
      if (document.body.currentStyle) {
        // 在ie下兼容写法
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {
      console.log(e)
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop

      const screenWidth = document.body.clientWidth // body当前宽度
      const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取)

      const dragDomWidth = dragDom.offsetWidth // 对话框宽度
      const dragDomheight = dragDom.offsetHeight // 对话框高度

      const minDragDomLeft = dragDom.offsetLeft
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

      const minDragDomTop = dragDom.offsetTop
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight

      // 获取到的值带px 正则匹配替换
      let styL = sty(dragDom, 'left')
      // 为兼容ie 
      if (styL === 'auto') styL = '0px'
      let styT = sty(dragDom, 'top')

      // console.log(styL)
      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100)
        styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100)
      } else {
        styL = +styL.replace(/px/g, '')
        styT = +styT.replace(/px/g, '')
      };

      document.onmousemove = function (e) {
        // 通过事件委托,计算移动的距离
        let left = e.clientX - disX
        let top = e.clientY - disY
        // 边界处理
        if (-(left) > minDragDomLeft) {
          left = -(minDragDomLeft)
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {
          top = -(minDragDomTop)
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop
        }

        // 移动当前元素
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`

        // emit onDrag event
        // vnode.child.$emit('dragDialog')
      }

      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
      return false
    }
  }
})

main.js 中全局引用

import "./directives/directives";

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随便起的名字也被占用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值