美文网首页
useDrop vue 拖拽hook

useDrop vue 拖拽hook

作者: copyLeft | 来源:发表于2020-04-26 01:20 被阅读0次
xx.gif

使用例子

  <style>

*{
  margin: 0;
  padding: 0;
}

li{
  list-style: none;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

ul{
  margin: auto;
  width: 400px;
}

li{
  display: flex;
  justify-content: space-between;
  padding: 8px 16px;
  border: 1px solid #eee;
  border-radius: 4px;
  background: #fff;
}

li + li{
  margin-top: 10px;
}

button{
  padding: 6px 12px;
  background: #efefef;
  border-radius: 4px;
  border: 0;
  box-shadow: 0;
}

button.full{
  display: block;
  box-sizing: border-box;
  width: 100%;
  
}

.card{
  margin: 20px auto;
  padding: 10px 20px;
  width: 400px;
  border-radius: 6px;
  box-shadow: 0 -4px 16px 4px rgba(100, 100, 100, .1);
}


.area{
  
  height: 200px;
  background: #eee;

}

.move{
  display: inline-block;
  margin: 10px;
  width: 50px;
  height: 50px;
  border-radius: 4px;
  border: 1px dashed orange;
}

</style>
<template>
  <div id="app">
    
    <div class="card">
      isHovering: {{ isHovering }}
    <div class="area" v-on='dropEvent' ></div>

      <div>
        <div 
          v-for='item of [...state]' 
          class="move" 
          :key='item' 
          @click='remove(item)'
          :ref='addEle(item)'>
        </div>

        <button @click='addHandler' > add </button>
      </div>

    </div>
    
    
  </div>
</template>

<script>
import { useSet, useDrag, useDrop } from 'vx-hook'

export default {
  name: 'App',
  components:{
    
  },
  setup(){

    const [ dropEvent, { isHovering } ] = useDrop({
      onDom(text){ console.log(text) }
    })
    
    const [ state, { add, remove } ] = useSet([])
    

    const addEle = useDrag()

    const addHandler = () => add(new Date())

    return {
      addHandler,
      state,
      add,
      remove,
      addEle,
      dropEvent,
      isHovering
    }
  }
}
</script>

接口

useDrop

拖拽区事件

Params

  • options

    • onDom dom拖拽释放回调
    • onUri uri拖拽释放回调
    • onFiles file拖拽释放回调
    • onText text拖拽释放回调

Result

  • props 拖拽监听函数
    • dragover e => void
    • dragenter e => void
    • dragleave e => void
    • drop e => void
    • paste e => void
  • isHovering 是否进入监听区 boolean

useDrag

被拖拽dom

Result

  • addEle 数据及元素绑定函数 any => ele => void
   <div 
      v-for='item of [ 1, 2, 3 ]' 
      class="move" 
      :key='item'
      :ref='addEle(item)'>
    </div>

实现

import { ref, watch } from 'vue'

const CUSTOM = 'CUSTOM'

export function getDragDomSign(){
    return CUSTOM
}

export function domDragCallback(){
    return data => ({ dataTransfer }) => dataTransfer.setData(CUSTOM, JSON.stringify(data))
}

/**
 * DOM 拖拽快速绑定hook
 * @returns { function } 
 * - addEle any => element => void 接收事件传参,返回dom元素收集器
 */
export function useDrag(){

    const elems = ref([])
    const handlers = ref([])
  
    watch(() => elems.value, (val, oldVal) =>{
  
      if(oldVal){
        oldVal.forEach((ele, index) => {
          ele.removeEventListener('onDragstart', handlers.value[index])
          handlers.value.splice(index, 1)
          elems.value.splice(index, 1)
        })
      }
  
      if(val){
        val.forEach((ele, index) => {
          ele.setAttribute('draggable', true)
          ele.addEventListener('dragstart', handlers.value[index])
        })
      }
    })
  
    const addEle = data => ele => {
      
       if(!ele){return}
       handlers.value = [ ...handlers.value, ({ dataTransfer }) => {
        dataTransfer.setData(CUSTOM, JSON.stringify(data))
      } ]
      elems.value = [ ...elems.value, ele ]
    }
   
   return addEle
   
}


/**
 * 拖拽事件
 * @param {*} callback 
 * @param {*} setIsHovering 
 * @return { obejct } 监听函数
 */
function getProps( callback, setIsHovering ) {

    return {
        dragover: e => e.preventDefault(),
        dragenter: e => { e.preventDefault(); setIsHovering(true) },
        dragleave: () => { setIsHovering(false) },
        paste: e => callback(e.dataTransfer, e),
        drop: e => {
         e.preventDefault();
         setIsHovering(false);
         callback(e.dataTransfer, e);
       }
     }
    
}
  

/**
 * 拖拽区hook
 * @param { Object } options 
 * - onDom dom拖拽释放回调
 * - onUri uri拖拽释放回调
 * - onFiles file拖拽释放回调
 * - onText text拖拽释放回调
 * 
 * @returns { array  }
 * - props 拖拽监听函数
 * - isHovering 是否进入监听区
 */
 export function useDrop(options={}){
    
    const optionsRef = ref(options)
    const isHovering = ref(false)
    const setIsHovering = status => isHovering.value = status
    
    const callback = (dataTransfer, event) =>{
  
      const url = dataTransfer.getData('text/uri-list')
      const dom = dataTransfer.getData(CUSTOM)
  
      const { onDom, onUri, onFiles, onText } = optionsRef.value
      
    
      if(dom&&onDom){
        onDom(JSON.parse(dom), event)
        return
      }
  
      if(url&&onUri){
        onUri(url, event)
        return
      }
  
      if(dataTransfer.files && dataTransfer.files.length && onFiles){
        onFiles( [...dataTransfer.files], event )
        return 
      }
  
      if(dataTransfer.items&&dataTransfer.items.length&&onText){
        dataTransfer.items[0].getAsString(text => onText(text, event))
      }
      
    }
    
    const props = getProps(callback, setIsHovering)
  
  
    return [ props, { isHovering } ]
    
}

  • vx-hook vue3.0 hook工具, umi hook vue实现

相关文章

网友评论

      本文标题:useDrop vue 拖拽hook

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