hook-拖拽

2020-07-03  本文已影响0人  skoll

两个是完全不能借鉴对方的思路

1 .如果vue强行用react这种写法的话,出来的效果是很卡顿的。

import {useEffect,useState} from 'react'

export default function useDraggable(refEl){
    const [{dx,dy},setOffset]=useState({dx:0,dy:0})
    
    useEffect(()=>{
        function handleMouseDown(e){
            // console.log('一直在点击')
            // 一开始我是觉得每次dx,dy变化这个函数每次都执行,绑定在document上的事件是否会重新绑定,这样会不会造成浪费,上面的log打印出来发现只会绑定一次,尽管这个会重复执行

            const startX=e.pageX-dx
            const startY=e.pageY-dy

            console.log('一直在点击')
            // 这里也是用的最一开始按下的变量,我的写法是需要每次都重新设置的
            function handleMouseMove(event){
                
                const newDx=event.pageX-startX
                const newDy=event.pageY-startY
                setOffset({dx:newDx,dy:newDy})
            }

            // 这里找到按下鼠标的坐标,接下来移动的位置是相对于这个坐标的
            // 在按下的时候触发了mousemove事件

            document.addEventListener('mousemove',handleMouseMove)
            //最关键的是他在鼠标按下的事件里面定义和绑定了鼠标移动事件 

            // 并且在鼠标按下的时候定义了鼠标释放事件,这就导致了必然会已这个为前提的。
            document.addEventListener('mouseup',()=>{
                console.log('释放了鼠标')
                // 然后在鼠标拿起的时候解绑mousemove事件。这个嵌套的写法没看过,但是仔细一样又是这么合理
                document.removeEventListener('mousemove',handleMouseMove)
            },{once:true})
        }
        
        // 最外面是这个绑定:首先检测是否已被按下
        refEl.current.addEventListener("mousedown",handleMouseDown)
        return ()=>{
            refEl.current.removeEventListener("mousedown",handleMouseDown)
        }
    },[dx,dy])

    // 简单而优美。。


    // 下面是用Vue的思想来写reatc的拖拽组件,还有一个vue实现react思想的拖拽,出现明显的停滞效果
    // 感觉他这个实现和之前认识的不太一样,理解起来有点麻烦,需要按照自己的理解写一下
    // 按照自己的理解写的,传入effect的参数变多,函数变多,设置的变量变多,还有bug
    

    // 我的用来决定是否是拖拽的是一个变量,鼠标move改变元素的位移是以这个为前提的,但是有的时候这个消不掉,就导致明明鼠标已经放开了,但是还在处于拖拽状态。
    // const [isClick,setClick]=useState(false)
    // const [{startX,startY},setStartXY]=useState({startX:0,startY:0})

    // function handleMouseDown(e){
    //     console.log('click')
    //     setClick(true)
    //     const x=e.pageX-dx
    //     const y=e.pageY-dy
    //     console.log('startX',x,y)
    //     setStartXY({startX:x,startY:y})
    // }

    // function handleMouseUp(){
    //     console.log('unClick')
    //     setClick(false)
    // }

    // function handleMouseMove(e){
    //     if(isClick){
    //         const newDx=e.pageX-startX
    //         const newDy=e.pageY-startY
    //         console.log('nX',newDx,'nY',newDy)
    //         setOffset({dx:newDx,dy:newDy})
    //     }else{
    //         console.log('没有按下,现在应该是不对的')
    //     }  
    // }

    // useEffect(()=>{
    //     refEl.current.addEventListener('mousedown',handleMouseDown)
    //     refEl.current.addEventListener('mouseup',handleMouseUp)
        
    //     document.addEventListener('mousemove',handleMouseMove)
    //     return ()=>{
    //         refEl.current.removeEventListener('mousedown',handleMouseDown)
    //         refEl.current.removeEventListener('mouseup',handleMouseUp)
    //         document.removeEventListener('mousemove',handleMouseMove,{once:true})
    //     }
    // },[dx,dy,isClick,startX,startY])
    // 这个里面不加isClick的意思,这些函数取到的值里面的isClick值会是初始状态的值,所以在这个值变化的时候要重新挂载一下这个函数,vue里面倒是不用这么写

    // 上面这个里面的一个函数不停的修改这个函数,不断触发他自己,也触发下面的函数,如果不传dx,dy的话,每次拖conso
    useEffect(()=>{
        refEl.current.style.transform=`translate3d(${dx}px,${dy}px,0)`
    },[dx,dy])
}

1 .vue版本

const liCmd=new Vue({
    el:"#cmd",
    data:function(){
        return {
          offsetX:0,
          offsetY:0,
        }
    },
    template:`
      <div class="li-cmd" :style="computedStyle" @mousedown="handleClick" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave"> 
          <div class="li-cmd-last">
              <span v-for="(c,index) in lastCmd"  @click="handleLast(c)">
                {{c}}
                <span @click.stop="handleRemove(index)" class="li-cmd-close">x</span>
              </span>
          </div>
          <div class="li-cmd-often">
              <span v-for="c in oftenCmd" @click="handleOften(c)">{{c}}</span> 
              <span v-for="(c,index) in oftenCmdJoin" @click="handleOftenJoin(index)">{{c}}<span/>
          </div>
      </div>
    `,
   
      handleClick(e){
          const startX=e.pageX-this.offsetX
          const startY=e.pageY-this.offsetY

          console.log('一直在点击')

          let _this=this
          function handleMouseMove(e){
            // console.log('鼠标移动呢')
            const newDx=e.pageX-startX
            const newDy=e.pageY-startY
            _this.offsetX=newDx
            _this.offsetY=newDy
            // 这里的this竟然是整个document
            // 我还以为需要使用this.$foreceUpdate()强制刷新一遍才行
          }
          
          document.addEventListener('mousemove',handleMouseMove)
          document.addEventListener('mouseup',()=>{
            document.removeEventListener('mousemove',handleMouseMove)
          },{once:true})
      }
    },
    computed:{
      computedStyle(){
        let x=this.offsetX
        let y=this.offsetY
        if(this.isFocus){
          return {
            opacity:1,
            transform:`translate3d(${x}px,${y}px,0)`
          }
        }else{
          return {
            opacity:0.2,
            transform:`translate3d(${x}px,${y}px,0)`
          }
        }
      }
    }
})
上一篇下一篇

猜你喜欢

热点阅读