새소식

반응형
JavaScript/javascript

vanilla JS 동적 HTML 삽입 시 이벤트 리스너 및 스크립트 실행방법

  • -
반응형

Jquery 로 .html() 을 사용하여 동적 HTML 삽입 시 기존 노드와 기존 이벤트 리스너가 삭제되지만

.on() 으로 등록했던 이벤트 리스너들은 Jquery 가 재 바인딩을 해줘 이벤트를 사용할 수 있었다.

 

하지만 vanilla JS 의 .innerHTML 을 통해 동적 HTML 삽입 시 기존 노드 및 기존 이벤트 리스너가 삭제된 후

.addEventListener() 를 통해 이벤트를 수동으로 재등록 해줘야 사용할 수 있다.

 

이때 vanilla JS 로 동적 HTML 삽입 시 이벤트 리스너 및 스크립트를 실행할 수 있는 방법은

공통 함수를 호출하여 함수 내 스크립트 태그내용을 불러와서 재등록 해주면 된다.

 

본인은 모달창을 띄울때 모달창 내용을 동적 HTML 삽입하여 띄웠다.

 

const initializeModalContent = function(modalElement, htmlContent, options = {}) {
    // 1. 기본 옵션 설정
    const defaultOptions = {
        show: true,
        backdrop: 'static',
        keyboard: true,
        focus: true
    };
    
    // 사용자 옵션과 기본 옵션 병합
    const modalOptions = { ...defaultOptions, ...options };

    // 2. 스크립트 태그들을 추출하고 내용 저장
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = htmlContent;
    const scripts = Array.from(tempDiv.getElementsByTagName('script'))
        .map(script => ({
            attributes: Array.from(script.attributes),
            content: script.textContent
        }));

    // 3. HTML 콘텐츠 삽입
    modalElement.innerHTML = htmlContent;

    // 4. 스크립트 재생성 및 실행
    scripts.forEach(script => {
        if (!script.content) return;
        
        const newScript = document.createElement('script');
        script.attributes.forEach(attr => {
            newScript.setAttribute(attr.name, attr.value);
        });
        newScript.textContent = script.content;
        modalElement.appendChild(newScript);
    });

    // 5. 모달 표시 (옵션이 제공된 경우)
    if (modalOptions.show) {
        const modal = new bootstrap.Modal(modalElement, {
            backdrop: modalOptions.backdrop,
            keyboard: modalOptions.keyboard,
            focus: modalOptions.focus
        });
        modal.show();
    }

    // 6. 모달 컨텐츠 로드 완료 이벤트 발생
    modalElement.dispatchEvent(new CustomEvent('modalContentLoaded'));
};

 

이러한 함수를 사용하여 동적 HTML 파일 내 스크립트 내용을 재등록 해준다.

이때 동적 HTML 파일 내 document.addEventListener("DOMContentLoaded", () => {}) 를 제거해줘도

동적 HTML 파일 삽입 후 스크립트를 재등록해주면 사용이 가능하다.

 

// .innerHTML 을 통한 동적 HTML 삽입
document.getElementById('testDialog').innerHTML = response.data;

// 동적 HTML이 삽입된 DOM 호출
const modalElement = document.querySelector('#testDialog');

// 모달 공통 유틸리티
initializeModalContent(modalElement, response.data, {
    backdrop: 'static',
    keyboard: false
});

// HTML
<div class="modal draggable fade in" id="testDialog"  tabindex="-1" role="modal" aria-hidden="true" >
</div>

 

.innerHTML 을 통해서 동적 HTML 파일을 삽입해주고 initializeModalContent 공통 함수로 스크립트를 재등록 해준다.

 

 

문제점 : 상위에 스크립트가 등록되어 있으면 DOM 이 그려지기 직전에 호출되면 호이스팅 문제로 에러가 발생한다.

이유는 상위의 스크립트 내용 중 DOM 이 그려진 후 호출되어야 하는 스크립트가 존재할 경우 에러가 발생한다.

 

해결하기 위해선 addEventListener('modalContentLoaded', () =>{}) 를 통해서

모달창 컨텐츠가 로드된 후 실행하도록 코드를 추가해주면 된다.

 

document.querySelector('#testDialog').addEventListener('modalContentLoaded', () => {
	... 모달창이 로드된 후 실행될 코드
});

 

 

 

 

 

 

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.