使用例子
<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实现
网友评论