index.html, index.css 는 달라진 부분이 없음!
대부분의 갤러리앱에서 이미지를 삭제할 경우
편집 -> 이미지 다수 선택 -> 삭제
이미지 선택 -> 삭제
위 두 가지 과정이 보편적임
로컬서버에 이미지가 몇개 없기도하고, 이미지 각 별개로 삭제기능을 추가하는 것이 좀 더 구현하기 편할 것 같아서 이미지 선택 -> 삭제
의 방법으로 구현해 보기로 했음
└ 이미지를 받아오고 삭제하기까지의 과정
└ 'onmouse' 이벤트로 인해 보여지는 삭제 아이콘을 클릭하면 해당 이미지를 삭제요청함
메소드 경로 요청데이터 응답데이터 설명 1 GET /fileList yy:년도, mm:월 fileList: 파일리스트 서버에서 파일마다의 절대경로를 받아옴 2 GET /file idx: 인덱스 fileList[idx]: idx번째 파일 순서대로 파일을 하나씩 받아옴 3 DELETE /file idx: 인덱스 fileList[idx]: idx번째 파일 해당하는 파일을 삭제
이미지에 마우스를 올리면, 이미지가 옆으로 옮겨지면서 숨겨진 아이콘들이 보여지게 하고 싶었음
└ 구상한 구조, 아래의 imgCard() 가 리턴하는 element
tag구분을 className 기준으로 한 것 처럼 보이는데, 실수로 아래 js 코드의 document.createElement()로 할당한 변수이름을 기준으로 tag를 구분했네요🤦♂️...🙇♂️🙇♂️🙇♂️
└ 실제 동작
위를 구현하기 위해 z-index로 z축을 설정하고, 'onmouse' 이벤트마다 <img>
의 위치를 변경해 주었음
받아온 fileList의 수 만큼 아래의 imgCard()로 요소생성
index.js 📝
const imgCard = (fileList, item, idx) => {
let trashIcon = 'fa-solid fa-trash fa-2xl';
let extenseIcon = 'fa-solid fa-up-right-and-down-left-from-center fa-2xl';
let card = document.createElement('div');
let space = document.createElement('div');
let movingBlock = document.createElement('div');
let img = document.createElement('img');
let hiddenSpace = document.createElement('div');
let hiddenDiv1 = document.createElement('div');
let hiddenDiv2 = document.createElement('div');
let hiddenIcon1 = document.createElement('i');
let hiddenIcon2 = document.createElement('i');
card.setAttribute("idx", idx);
hiddenIcon1.className = trashIcon;
hiddenIcon2.className = extenseIcon;
hiddenDiv1.appendChild(hiddenIcon1);
hiddenDiv2.appendChild(hiddenIcon2);
hiddenSpace.append(hiddenDiv1, hiddenDiv2);
img.src = URL.createObjectURL(item);
img.alt = `loaded image num ${idx + 1}`;
movingBlock.append(img, hiddenSpace);
card.append(space, movingBlock);
hiddenDiv1.className = 'hidden-div';
hiddenDiv2.className = 'hidden-div';
img.className = 'loaded-imgs';
card.className = 'img-card';
space.className = 'space';
movingBlock.className = 'moving-block';
hiddenSpace.className = 'hidden-space';
card.style =
'display : flex;position: relative;margin: 10px;width: 250px;height: 200px;z-index: 1;';
space.style = 'width: 50px;';
movingBlock.style = 'width: 220px; margin-right: 20vw;';
img.style =
'position: absolute;left: 50px;width: 200px;height: 200px;z-index: 2;object-fit: fill;border: 1px solid #000;';
hiddenSpace.style =
'position: absolute;left: 200px;width: 50px;display: flex;flex-direction: column;height: 100%;';
hiddenDiv1.style =
'display: flex;flex: 1;justify-content: center;align-items: center;margin-left: 5px;';
hiddenDiv2.style =
'display: flex;flex: 1;justify-content: center;align-items: center;margin-left: 5px;';
movingBlock.addEventListener('mouseover', function () {
this.firstChild.style =
'position: absolute;left: 0px;width: 200px;height: 200px;z-index: 2;object-fit: fill;border: 1px solid #000;';
});
movingBlock.addEventListener('mouseout', function () {
this.firstChild.style =
'position: absolute;left: 50px;width: 200px;height: 200px;z-index: 2;object-fit: fill;border: 1px solid #000;';
});
hiddenIcon1.addEventListener('mouseover', function () {
this.style = 'color: red;';
});
hiddenIcon1.addEventListener('mouseout', function () {
this.style = 'color: black;';
});
hiddenDiv1.addEventListener('click', function(){
if(confirm("정말로 이 사진을 삭제하시겠습니까?\n")){
removeFile(fileList[idx]).then((result) => {
console.log(result);
})
});
}
});
hiddenIcon2.addEventListener('mouseover', function () {
this.style = 'color: red;';
});
hiddenIcon2.addEventListener('mouseout', function () {
this.style = 'color: black;';
});
// 여기는 this를 통해 태그 속성을 이용하기위해 arrow 가 아닌 일반함수로 선언
return card;
};
// 이미지 삭제
const removeFile = async (filePath) => {
const response = await fetch(baseUrl + 'file', {
method: 'DELETE',
headers: {
path: filePath,
},
});
if (!response.ok) {
alert("Error : Function Name 'removeFile'");
}
return response;
};
.
.
.
동적으로 화면을 변경하는 대부분의 로직이 js에 과부화 되어있음
element.style = '~'
로 적용해주기 때문에 코드의 길이가 길어져 좋지 않은 코드가 되었음무엇보다 이미지를 삭제하면, 새로고침해서 다시 해당 년/월을 받아와야 이미지가 사라진것을 볼 수 있음
index.js 📝 ( 삭제 아이콘 클릭이벤트 부분만 )
hiddenDiv1.addEventListener('click', function(){
if(confirm("정말로 이 사진을 삭제하시겠습니까?\n")){
removeFile(fileList[idx]).then((result) => {
console.log(result);
});
}
});
위 아이콘을 클릭하면
이렇게 메세지 박스가 뜨는데 위 어느 버튼을 클릭하더라도
위 처럼 [Violation]
경고가 뜬다.
위 사진에서의 '1263ms', '1682ms' 는 위 'click' 이벤트로 실행되는 confirm() 의 메세지 박스에서 '확인' 또는 '취소' 버튼을 누를때 까지 걸리는 시간이었다.
그냥 무시해도 겉으로 보기엔 문제가 없겠지만 이러한 잔 경고라도 안뜨게 하고 싶었다.
문제를 해결하기 위해 해당 오류를 검색해보니, 리턴받는데 시간이 걸리는 함수는 비동기 함수로 작성해서 스크립트의 속도를 조금이라도 높이라는 의미였고,
크롬 브라우저의 개발자 모드에서 웹 개발자로 하여금 조금 더 웹의 성능을 향상시키도록 돕는 기능이었다. 경고라기 보단 약간 제안같은 느낌이랄까...?
confirm() 이 내 웹의 다른 동작을 막거나 지연시키는 것은 아니라 생각이 들어서 그냥 그대로 두었지만, 만약 위와 같은 [Violation]
이 발생하면 어떤 부분에서 발생한 것인지 체크해볼 필요는 있는 것 같다.