美文网首页
hook-拖拽

hook-拖拽

作者: skoll | 来源:发表于2020-07-03 17:36 被阅读0次

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

    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)`
              }
            }
          }
        }
    })
    

    相关文章

      网友评论

          本文标题:hook-拖拽

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