Разбираемся с конфликтом событий в Vue.js
Недавно я столкнулся с интересной проблемой в рабочем Vue.js приложении. При попытке скопировать текст из определенного компонента (выделив его мышью и нажав Ctrl+C или используя контекстное меню), в буфер обмена вместо выделенного текста попадала строка
[object ClipboardEvent]. При этом в других компонентах копирование работало нормально.Причина проблемы
После долгих исследований я обнаружил истинную причину проблемы: конфликт имен между нативным событием браузера и пользовательским событием Vue.
В моем компоненте был метод
copy , который эмитил событие с именем "copy" в родительский компонент:copy(value) {
this.$emit("copy", value);
}А в родительском компоненте был обработчик этого события:
<order-info-lines :info="orderInfo" @copy="copy" />
...
copy(value) {
navigator.clipboard.writeText(value);
}
Проблема возникала из-за того, что браузер также имеет нативное событие
"copy". Vue перехватывал это нативное событие и пытался передать его в обработчик, который ожидал получить значение для копирования, а не объект события.Решение
Решение оказалось простым: нужно было избежать конфликта имен, переименовав пользовательское событие Vue.
// переименовать copy на copyValue
copy(value) {
this.$emit("copyValue", value);
}
И так же обновить все места в родительском компоненте
<order-info-lines :info="orderInfo" @copyValue="copy" />
После этих изменений копирование текста стало работать корректно.
Выводы
1. Избегайте использования имен нативных событий браузера для пользовательских событий Vue. Вот некоторые распространенные нативные события, которые лучше не использовать для пользовательских событий:
click, copy, paste, cut, focus, blur, input, change, submit, keydown, keyup, mousedown, mouseup, mousemove.2. Используйте префиксы для пользовательских событий. Хорошей практикой является добавление префикса к именам пользовательских событий, например:
on-copy, handle-copy, custom-copy или, как в моем случае, copyValue.