우당탕탕 개발일지
To-Do List 만들기 2차 본문
3. Loading() 함수 만들기
3-3. innerHTML활용해서 html 삽입하기
( 앞서 To-Do List 만들기 1차에서는 제이쿼리를 사용해서 html 코드를 삽입하였다. )
1차 시도
getElementById() 메서드를 사용하여 id가 "htmlList"인 HTML 요소에 접근한다.
반환 값을 element 변수에 넣어준 뒤, innerHTML을 호출하여 element 뒤에 프로퍼티의 값을 넣어주려 했지만 오류가 발생했다. element에 값을 추가해주는 것이 아닌 값을 대입해서 발생한 문제였다. 즉, ToDos의 배열을 순회하면서 element의 값을 4번씩 초기화 해 준 것이었다.
const element = document.getElementById('#htmlList');
ToDos.forEach(todo => {
element.innerHTML = '<div class="To-Do">';
element.innerHTML =' <input id="checkButton" type="checkbox" onclick="Check(todo.number)" />';
element.innerHTML =' <div class="list">${todo.content}</div>';
element.innerHTML =' <div id="deleteButton" onclick=Delete(todo.number)> X </div></div>';
});
2차 시도
삽입할 html 코드 전체를 완성시킨 뒤 마지막에 한번에 넣는 방식으로 수정하였다.
ToDos.forEach(todo => {
htmlList += `
<div class="To-Do">
<input
id="checkButton"
type="checkbox"
onclick="Check(todo.number)"
/>
<div class="list">${todo.content}</div>
<div id="deleteButton" onclick=Delete(todo.number)> X </div>
</div>
`
});
//오류 발생 구간
const element = document.getElementById('#htmlList');
element.innerHTML = htmlList;
다음과 같은 에러가 발생했다. 이것은 DOM 요소를 로딩하는 부분에서 생긴 오류이다. 오류 발생 원인 예상은 다음과 같다.
- 요소가 웹 페이지에 나타나기 전에 스크립트 배치
- 잘못된 요소 ID를 참조
오류 원인을 분석하기 위해 element 콘솔을 찍어보았다.
element가 null로 찍히길래 element 요소를 살펴보니, getElementById를 CSS처럼 #으로 불러와서 발생한 오류였다. 수정하면 다음 코드와 같다.
const element = document.getElementById('htmlList');
element.innerHTML = htmlList;
3-4. insertAdjacentHTML 활용해서 html 삽입하기 (참고)
단순히 텍스트만 입력하기 위해서라면 innerText 만으로도 충분하고, 무엇보다 innerHTML은 매우 느린데다 외부 공격에 취약하여 가급적 사용을 지양해야 하는 기능이라는 글을 보게 되었다. innerHTML 보다 createElement 및 append 등을 사용하는 것이 성능상 이점이 있지만, 작성하기에 상당히 피곤하며 가독성도 떨어지는 단점이 있었고, innerHTML과 사용법이 비슷하면서도 가독성도 확보되고 월등한 성능을 지닌 insertAdjacentHTML을 사용해보기로 하였다.
내부 HTML 코드를 JS 내에서 변경할 수 있도록 해주는 속성으로는 innerHTML과 innerText 등이 있다.
● element.innerText
이 속성은 element 안의 text 값들만을 가져온다.
● element.innerHTML
innerText와는 달리 innerHTML은 element 안의 HTML이나 XML을 가져온다.
< 웹페이지 텍스트에 접근하는 3가지 속성의 차이점 >
● 웹페이지 요소의 텍스트 내용만 바꿀 경우 => Node.textContent 속성 사용
● 웹페이지 요소 자체를 삽입할 경우 => Element.insertAdjacentHTML() 메서드 사용
● element.insertAdjacentHTML (position, text)
HTML or XML 같은 특정 텍스트를 파싱하고, 특정 위치에 DOM tree안에 원하는 node들을 추가 한다.
이미 사용중인 element는 다시 파싱하지 않으며, element안에 존재하는 다른 element를 건드리지 않는다.
- position
- ‘beforebegin’, element 앞에
- ‘afterbegin’, element 안에 첫번째 child
- ‘beforeend’ element 안에 가장 마지막 child
- ‘afterend’ element 뒤에
- text
- text(인자)는 HTML or XML로 해석될 수 있는 문자열(html code), (DOM) tree에 삽입할 수 있다.
insertAdjacentHTML의 경우 원래 있던 element를 건드리지 않기 때문에 forEach를 사용할 필요가 없었다.
다음 4가지 방법 중 세 번째 방법인 Array.at()을 사용하기로 하였다.
< 배열의 마지막 요소 가져오기 >
1. 'Array.length - 1'으로 배열의 마지막 요소 접근
2. 'Array.slice(-1)[0]'으로 배열의 마지막 요소 접근
3. Array.at()으로 배열의 마지막 요소 접근
4. Array.pop()으로 배열의 마지막 요소 가져오기
● Array.prototype.at()
- at() 메서드는 정수 값을 받아, 배열에서 해당 값에 해당하는 인덱스의 요소를 반환한다.
- 음수 값의 경우 배열의 뒤에서부터 인덱스를 센다.
- 맨 마지막 요소를 가져오고 싶을 때 length 속성을 사용해 array[array.length - 1]을 하는 대신, 짧게 array.at(-1)을 사용할 수 있다.
변수 htmlList에 ToDos 배열의 마지막 정보를 입력해주는 html 코드를 넣어준다. getElementById() 메서드를 사용하여 id가 "htmlList"인 HTML 요소에 접근한다. 반환 값을 element 변수에 넣어준 뒤, insertAdjacentHTML을 호출하여 element 뒤에 프로퍼티의 값을 삽입한다.
const htmlList = `
<div class="To-Do">
<input
id="checkButton"
type="checkbox"
onclick="Check()"
/>
<div class="list">${ToDos.at(-1).content}</div>
<div id="deleteButton" onclick=Delete(ToDos.at(-1).number)> X </div>
</div>
`;
const element = document.getElementById('htmlList');
element.insertAdjacentHTML('beforeend', htmlList);
※ 반복문을 통해 htmlList에 html 코드를 작성하는게 아니다 보니 함수에 파라미터를 넣어주지 못한다는 변수가 발생하였고, 기존의 innerHTML을 이용하기로 하였다.
'Front-end > JavaScript' 카테고리의 다른 글
비동기 프로그래밍 (0) | 2023.05.16 |
---|---|
DOM & EVENT (코딩앙마) (0) | 2023.04.27 |
To-Do List 만들기 3차 (0) | 2023.04.11 |
To-Do List 만들기 1차 (0) | 2023.04.03 |
To-Do List - JS 문법 (0) | 2023.03.29 |