可视化操作,少不了拖拽这个环节。只是不想用现成的拖拽库,而是想自己弄一个。
先拿 table 开刀吧。
有一个table的表格,想通过拖拽表头(th)来实现调整先后顺序的功能,于是做了这个可以拖拽 th 的自定义指令。
优点:
- 不破坏现有结构。
- 支持各种table,各种UI库的table的组件,只要渲染后是一个table即可。
缺点:
- 不会做特效,默认的拖拽效果,不好看。
- 自定义指令只实现拖拽效果,返回拖拽信息,不实现具体功能。
可以拖拽 th 的自定义指令
/**
* 拖拽 table 的 th,返回拖拽信息
*/
const tableDrag = (app, options) => {
app.directive('tabledrag', {
// 指令的定义
mounted (el, binding) {
// console.log('===== el', el)
// console.log('===== binding', binding)
binding.value.setTdforDrag = (className, dragInfo) => {
const table = el.getElementsByClassName(className)[0]
const tr = table.rows[0]
const tdCount = tr.cells.length
// 设置th的拖拽
for (let i = 0; i < tdCount; i++) {
const th = tr.cells[i]
// 设置可以拖拽
th.setAttribute('draggable', true)
// 拖拽时经过
th.ondragover = (event) => {
event.preventDefault()
}
// 开始拖拽
th.ondragstart = (event) => {
// console.log('ondragstart - event', event)
dragInfo.source = event.target.innerText
}
// 结束拖拽
th.ondrop = (event) => {
// console.log('ondrop - event', event)
dragInfo.offsetX = event.offsetX
dragInfo.ctrl = event.ctrlKey
dragInfo.target = event.target.innerText
// console.log('ondrop - dragInfo', dragInfo)
}
}
}
}
})
}
export default tableDrag
-
className
用于找到目标的 class 名称。 -
dragInfo
reactive 类型的对象,便于返回拖拽信息。 -
.ondragover
设置拖拽时经过的事件 -
.ondragstart
开始拖拽时的事件,可以得到th的部分信息,主要是其他的各种信息。 -
.ondrop
结束拖拽的事件 -
event.target.innerText
获取 th 的文本内容,目前只找到这个可以作为 th 的标识 -
event.offsetX
th 的鼠标的x的坐标 -
event.ctrlKey
结束拖拽时,是否按住 ctrl 键。
挂载指令
main.js
import { createApp } from 'vue'
import App from './App.vue'
// 拖拽table的th
import tableDrag from './control-web/js/tableDrag.js'
const app = createApp(App)
app.use(router) // 路由
.use(tableDrag) // table的拖拽
.mount('#app')
使用方法
<el-table
v-tabledrag="tableInfo"
v-bind="girdMeta"
:data-list="dataList"
:selection="dataListState.choice"
/>
const tableInfo = {
setThforDrag: () => {
console.log('原始的设置td的函数')
}
}
// 接收拖拽信息
const dragInfo = reactive({
offsetX: 0,
ctrl: false,
source: '',
target: ''
})
onMounted(() => {
nextTick(() => {
tableInfo.setThforDrag('el-table__header', dragInfo)
watch(() => dragInfo, () => {
console.log('外部:', dragInfo)
},
{ deep: true })
})
})
这里有个麻烦的地方,应该是渲染完毕,自定义指令的 mounted 才会被调用。
但是并不是!
这时候table或者里面的th还没有出来呢。
如果在组件里面使用 onMounted ,以为这时候应该出来了吧,结果还是没有。
于是只好再加上nextTick,这次终于出来了。
因为 dragInfo 是reactive类型的,具有响应性,所以我们可以监听,当拖拽结束的时候,就会触发。
本来想做成promise的,但是发现只能触发一次,第二次就不灵了。
这样拖拽后,我们就可以得到这样的数据:
拖拽信息我们可以根据 source、target 来判断是拖拽了哪个 th,然后做后续操作。
网友评论