본문 바로가기

trouble-shooting

vue app 외부에서 메소드 호출하기

크롬 익스텐션 프로그래밍을 하다가 난관에 부딪혔다. content 영역의 특정 버튼을 클릭하면 vue로 작성된 모달이 열리도록 했는데 이 때 모달이 열릴때마다 매번 데이터를 새로 불러오도록 설계했다. 간단히 코드로 설명하면 아래와 같다.

<button id="modal-button">버튼</button>
<div id="modal-app" style="display:none" data-is-visible="false"></div>

<script>
...

const button = document.getElementById("modal-button")
button.addEventListener("click", () => {
  const modalDiv = document.getElementById("modal-app")
  if (modalDiv.dataset.isVisible === "false") {
    modalDiv.style.display = "block"
    modalDiv.dataset.isVisible = true
  } else {
    modalDiv.style.display = "none"
    modalDiv.dataset.isVisible = false
  }
})

const modalDiv = document.getElementById("modal-app")
const app = createApp(ModalVue)
app.mount(modalDiv)
</script>

 

문제는 모달을 여닫는 해당버튼은 vue app에 포함되지 않는다는 점이다. 데이터를 불러오는 메소드는 app내에 정의되어 있는데 어떻게 호출할 수 있을까? 이것이 내가 당면한 문제였다.

 

외부에서 app의 메소드에 직접적으로 접근해서 호출할수 있을지 방법을 찾아봤지만 아무래도 어려워보였다.

// 아래처럼 호출할 방법이 있을지 찾아봤다.
app.config.globalProperties.reloadData()

다행히 다른 해결방법을 찾아냈다. 버튼을 클릭할때 사용자 정의 이벤트를 발생시키는 것이었다.

<button id="modal-button">버튼</button>
<div id="modal-app" style="display:none" data-is-visible="false"></div>

<script>
...

const button = document.getElementById("modal-button")
button.addEventListener("click", () => {
  const modalDiv = document.getElementById("modal-app")
  if (modalDiv.dataset.isVisible === "false") {
    modalDiv.style.display = "block"
    modalDiv.dataset.isVisible = true
    window.dispatchEvent(new CustomEvent("reload-modal-data"))
  } else {
    modalDiv.style.display = "none"
    modalDiv.dataset.isVisible = false
  }
})

const modalDiv = document.getElementById("modal-app")
const app = createApp(ModalVue)
app.mount(modalDiv)
</script>


...
// ModalView.vue
<script>
...
export default {
  setup() {
    onMounted(async () => {
      window.addEventListener("reload-modal-data", loadData)
    })

    onUnmounted(() => {
      window.removeEventListener("reload-modal-data", loadData)
    })
  }
}
</script>

더 편한 방법이 없을까 GPT한테 물어봤는데 알려준 방법은 제대로 동작하지 않았다. app._instance가 undefined던데..