Как предотвратить выбор элемента Sortable JS при нажатии на один из его дочерних элементов? - PullRequest
2 голосов
/ 30 мая 2020

Проблема

Я использую Sortable JS для создания перетаскиваемого компонента дерева. Это означает, что каждый из моих sortable-item s имеет toggle-arrow в качестве дочернего элемента, который открывает и закрывает sub-tree (если он есть).

Я пытаюсь использовать stopPropagation() для предотвращения выбор родительского sortable-item, если toggle-arrow нажат, но он не работает.

В закрытом состоянии это выглядит так: enter image description here

И в открытом состоянии выглядит так: enter image description here

Синяя подсветка, которую вы видите в открытом состоянии (второе изображение), - это стиль, который я выбрал для опции selectedClass при использовании плагин multiDrag.

Это иллюстрирует, что когда я нажимаю на toggle-arrow, выбирается родительский sortable-item.

Я не хочу, чтобы это произошло.

Код

Код элемента в моем компоненте дерева Sortable JS выглядит так (с использованием Vue. js и синтаксиса Pug) :

div.sortable-item
    div.content
        div.toggle-arrow(@click.stop="toggleTree($event)")
        div.icon
        div.title
    div.sub-tree

И затем у меня есть обработчик для привязки @click к моему элементу toggle-arrow:

toggleTree = function($event) {
    $event.stopPropagation()
    /// Code for handling the sub-tree toggling goes here.
    /// The sub-tree toggling itself works just fine.
}

Вы можете видеть, что я объявляю @click.stop как событие b inding, который должен остановить всплытие события click из дочернего элемента toggle-arrow, но он не работает.

Я даже пытаюсь использовать $event.stopPropagation в обработчике. Но событие, кажется, продолжает пузыриться, и, таким образом, родительский элемент sortable-item оказывается в выбранном состоянии.

Я также пробовал объявить @click.native.stop как привязку события, но это просто мешает моему toggleTree метод от обстрела вообще. Я предполагаю, что где-то в пределах SortableJS есть другой обработчик событий, который мешает привязке @click.native.stop.

Вопросы

  1. Как мне остановить распространение события при нажатии на дочерний элемент моего sortable-item?

  2. Как выбор обрабатывается плагином multiDrag? Я покопался в коде и увидел, что событие select запускается в обработчике drop события из sortable-item, но меня это смущает. Почему обработчик событий drop используется для переключения выбора sortable-item?

Заранее благодарим вас за любой свет, который вы можете пролить на это.

Ответы [ 2 ]

3 голосов
/ 01 июня 2020

Неверное событие

Глядя на источник Sortable JS, кажется, что событие, которое вы хотите остановить от всплывания, не является событием click, а скорее mouseup событие.

enter image description here

Проблема «Застрявшего» элемента перетаскивания

Как указано в комментариях к этому ответу, остановка распространения события mouseup вызывает проблему, когда начинается перетаскивание непреднамеренно, и sortable-item «застревает» на указателе.

Кажется, что «инициирование перетаскивания» запускается событиями pointerdown, mousedown или touchstart, в зависимости от устройство.

Можно с уверенностью предположить, что событие pointerdown - это событие, которое запускает согласно caniuse.com .

enter image description here

Решение

Таким образом, фактический способ решить эту проблему - использовать привязку события @pointerdown.stop для запуска вашего метода toggleTree без запуска любого выбора из sortable-item или непреднамеренное перетаскивание.

div.sortable-item
    div.content
        div.toggle-arrow(@pointerdown.stop="toggleTree($event)")
        div.icon
        div.title
    div.sub-tree
2 голосов
/ 02 июня 2020

Измените

div.toggle-arrow(@click.stop="toggleTree($event)")

на

div.toggle-arrow(@click.native.stop="toggleTree($event)")

Если бы все, что вы сделали в toggleTree, было stopPropagation, вы могли бы изменить его на:

div.toggle-arrow(@click.native.stop)

Docs .

Короче говоря, в настоящее время вы останавливаете распространение при любых кликах, отправленных дочерним компонентом (также известное как пользовательское событие Vue, которое на самом деле не требует остановки распространения как по умолчанию он не пузырится). Что вы хотите сделать, так это вызвать event.stopPropagation() в собственном событии click.
В качестве альтернативы можно использовать:

div.toggle-arrow(@click.native="toggleTree($event)")

... и вызвать .stopPropagation() внутри toggleTree. Именно это и делает модификатор .stop.

...