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