gpt4 book ai didi

javascript - 将可拖动事件委托(delegate)给父元素

转载 作者:行者123 更新时间:2023-12-03 20:16:41 24 4
gpt4 key购买 nike

我有可拖动的 li 元素嵌套在 ul 中,而 ul 又嵌套在 div 中,如下所示:

  <div class='group'>
<div class='header'>
// some stuff here
</div>
<ul>
<li draggable='true'>
Stuff I want to drag and drop to another div.group
</li>
</ul>
</div>

这些 div 元素有多个,我正在尝试实现拖放功能以移动一个 divli 元素分组到另一个。

我在此处连接了 ondragenterondragleave 回调:

 // controller using mithril.js
ctrl.onDragLeave = function () {
return function (event) {
var target;
// Using isDropzone to recursively search for the appropriate div.group
// parent element, as event.target is always the children inside it
if ((target = isDropzone(event.target)) != null) {
target.style.background = "";
}
}
};
ctrl.onDragEnter = function () {
return function (event) {
var target;
if ((target = isDropzone(event.target)) != null) {
target.style.background = "purple";
}
};
};
function isDropzone(elem){
if(elem == null){
return null;
}
return elem.className == 'group' ? elem: isDropzone(elem.parentNode)
}

当回调的event.target总是嵌套在div中的子元素时,问题就来了,比如li,和因此回调不断被触发。在本例中,我通过回调更改了 div.group 的颜色,导致 div.group 意外闪烁。

有没有办法委托(delegate)事件,只允许 lidiv 祖父来处理事件?或者任何其他方法来解决这个问题?

编辑:仍然很想知道是否有办法做到这一点,但现在我正在使用我找到的解决方法 here .

最佳答案

所以这将符合“您需要从不同的 Angular 来处理这个问题”的答案类别。

尽可能避免在附加的处理程序中从 event.target/event.currentTarget 操作 DOM。

一些不同的事情:

  1. 您的 ondragleaveondragenter 处理程序应该简单地在您的 Controller /viewModel/stores 中设置一些适当的“状态”属性

  2. 当处理程序被解析时,这通常会触发 Mithril 中的重绘。在内部 m.startComputation() 启动,您的处理程序被调用,然后 m.endComputation()

  3. 您的“查看功能”再次运行。然后它会反射(reflect)更改后的模型。您的操作不会更改 View ,您的 View 会调用影响模型的操作,然后对这些更改使用react。 MVC,不是 MVVM


型号

在您的 Controller 中,设置一个模型来跟踪显示拖放用户界面所需的所有状态

ctrl.dragging = m.prop(null)

ctrl.groups = m.prop([
{
name: 'Group A',
dragOver: false,
items: ['Draggable One', 'Draggable Two']
},
...
// same structure for all groups
])

查看

在您的 View 中,设置一个反射(reflect)模型状态的 UI。让事件处理程序将有关操作的足够信息传递给 Controller ​​ - 足以使其能够正确响应相应操作模型的操作


return ctrl.groups.map(function (group, groupIdx) {
return m('.group',[
m('.header', group.name),
m('ul',
{
style: { background: (group.dragOver ? 'blue' : '')},
ondragleave: function () {ctrl.handleDragLeave(groupIdx)},
ondragenter: function () {ctrl.handleDragEnter(groupIdx)},
ondrop: function () {ctrl.handleDrop(groupIdx)},
ondragover: function (e) {e.preventDefault()}
},
group.items.map(function (item, itemIdx) {
return m('li',
{
draggable: true,
ondragstart: function () {ctrl.handleDragStart(itemIdx, groupIdx)}
},
item
})
)
])
})

现在它已设置好,以便该组可以通过对 Controller 中的状态/模型变化使用react来正确显示。我们不需要操纵 dom 来表示一个组有一个新项目,一个组需要一个新的背景颜色,或任何东西。我们只需要附加事件处理程序,以便 Controller 可以操纵您的模型,然后 View 将根据该模型重绘。

Controller

因此,您的 Controller 可以拥有处理程序,这些处理程序具有更新模型所需的操作的所有信息。

Controller 上的一些处理程序如下所示:

ctrl.handleDragStart = function (itemIdx, groupIdx) {
ctrl.dragging({itemIdx: itemIdx, groupIdx: groupIdx})
}

ctrl.handleDragEnter = function (groupIdx) {
ctrl.groups()[groupIdx].dragOver = true
}

ctrl.handleDragLeave = function (groupIdx) {
ctrl.groups()[groupIdx].dragOver = false
}

ctrl.handleDrop = function (toGroupIdx) {
var groupIdx = ctrl.dragging().groupIdx
var itemIdx = ctrl.dragging().itemIdx
var dropped = ctrl.groups()[groupIdx].items.splice(itemIdx, 1)[0]

ctrl.groups()[toGroupIdx].items.push(dropped)
ctrl.groups()[toGroupIdx].dragOver = false
ctrl.dragging(null)
}

尽量坚持 Mithril 的 MVC 模型事件处理程序调用 Controller 上的操作, Controller 操作模型。然后 View 对这些模型的变化使用react。这样就无需纠结于 DOM 事件的细节。

这是一个完整的 JSbin 示例,展示了您想要达到的目标:

https://jsbin.com/pabehuj/edit?js,console,output

我得到了预期的效果,根本不用担心事件委托(delegate)。

另外,请注意在 JSbin 中,ondragenter 处理程序:

ondragenter: function () {
if (ctrl.dragging().groupIdx !== groupIdx) {
ctrl.handleDragEnter(groupIdx)
}
}

这样可放置区域就不会改变其自身可拖动的颜色,这是我认为您在答案中寻找的内容之一。

关于javascript - 将可拖动事件委托(delegate)给父元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31917511/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com