티스토리 뷰
테이블 드래그 스크롤 구현을 완성했는데 클릭 이벤트와 충돌이 생겨서 해결했던 방법에 대해 정리한 글입니다.
기존에 테이블 row 클릭시 다이얼로그가 열렸고 드래그 스크롤 기능을 추가하면서 클릭 이벤트와 겹치는 문제가 발생했습니다. click과 mouseup 기준을 찾아서 구분을 주고 click 이벤트일 경우 다이얼로그가 열리도록 구현을 해봅니다.
MouseEvent
MouseEvent 인터페이스는 사용자가 포인팅 장치(마우스)와 상호 작용하여 발생하는 이벤트를 나타냅니다. 이 인터페이스를 사용하는 일반적인 이벤트는 다음과 같습니다. click, dblclick, mouseup, mousedown.
Element: mouseup event
mouseup 이벤트는 포인터가 내부에 있는 동안 포인팅 장치(예: 마우스 또는 트랙패드)의 버튼을 놓으면 요소에서 시작됩니다.
Element: click event
포인터가 요소 내부에 있는 동안 포인팅 장치 버튼(예: 마우스의 기본 마우스 버튼)을 눌렀다가 놓으면 요소에서 클릭 이벤트를 받습니다. click은 mousedown 및 mouseup 이벤트가 순서대로 발생한 후에 실행됩니다.
MouseEvent.pageX
MouseEvent 인터페이스의 pageX 읽기 전용 속성은 전체 문서의 왼쪽 가장자리를 기준으로 마우스를 클릭한 X(가로) 좌표(픽셀 단위)를 반환합니다.
HTMLElement.offsetLeft
HTMLElement.offsetLeft 읽기 전용 속성은 현재 요소의 왼쪽 위 모서리가 HTMLElement.offsetParent 노드 내에서 왼쪽으로 오프셋되는 픽셀 수를 반환합니다.
html
<div id="app">
<v-app>
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
class="elevation-1"
></v-data-table>
</v-app>
</div>
script
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
vueVersion: Vue.version,
vuetifyVersion: Vuetify.version,
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name'
},
{ text: 'KorName', value: 'korName' },
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
{ text: 'Note', value: 'note' },
],
desserts: [
{
name: 'Frozen Yogurt',
korName: '프로즌 요거트',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: 1,
note: '스크롤 테이블 이렇게 만드는건가? vue3 할지 react 할지 고민입니다.'
},
{
name: 'Ice cream sandwich',
korName: '아이스크림 샌드위치',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: 1,
note: '스크롤 테이블 이렇게 만드는건가? vue3 할지 react 할지 고민입니다.'
}
],
eventName: '' // 이벤트명
},
created () {
this.$nextTick(() => {
this.initDragScroll();
})
},
methods: {
initDragScroll () {
const slider = document.querySelector('.v-data-table__wrapper');
let isDown = false;
let startX;
let scrollLeft;
slider.addEventListener('mousedown', e => {
this.eventName = 'mousedown';
isDown = true;
slider.classList.add('active');
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', () => {
this.eventName = 'mouseleave';
isDown = false;
slider.classList.remove('active');
});
slider.addEventListener('mouseup', e => {
const x = e.pageX - slider.offsetLeft;
const walk = x - startX;
// 움직임이 없으면 click, 움직임이 있으면 mouseup
this.eventName = walk === 0 ? 'click' : 'mouseup';
alert(`이벤트: ${this.eventName} 움직임: ${walk}`);
isDown = false;
slider.classList.remove('active');
});
slider.addEventListener('mousemove', e => {
if (!isDown) return;
e.preventDefault();
const x = e.pageX - slider.offsetLeft;
const walk = x - startX;
slider.scrollLeft = scrollLeft - walk;
});
}
}
})
샘플 코드
https://codepen.io/juno1993/pen/OJobLBE
테이블 스크롤과 클릭 이벤트 구분
...
codepen.io
'vue js' 카테고리의 다른 글
[Vue.js] 컴포넌트 내 scoped style에 스타일이 적용 되지 않을때 v-deep으로 해결 (0) | 2023.01.12 |
---|---|
vue js reset component data (0) | 2019.07.24 |
댓글