Vue.js customed alert, modal

강정우·2023년 4월 2일
0

vue.js

목록 보기
20/72
post-thumbnail
post-custom-banner

alert implement

alert component

  • 우선 재사용이 가능한 경고 컴포넌트부터 만들어보자.

<template>
  <dialog open>
    <slot></slot>
  </dialog>
</template>

<style>
dialog {
	...
}
</style>
  • 우선 <dialog>로 뼈대를 잡아주고 내부에 children인 <slot> 을 넣어준다.

<dialog>

  • 내장 다이얼로그 요소를 표시하려면 open 속성이 필요하다. open이 없다면 동작하지 않는다.
    그러므로 이 다이얼로그를 표시하기 위해서 open 속성을 추가한다.

markup component

  • 이제 위에 만들어놓은 컴포넌트를 사용하러 가보자!
<template>
  <h2>Manage Goals</h2>
  <input type="text" ref="goal">
  <button @click="setGoal">Set Goal</button>
  <error-alert v-if="inputIsInValid">
    <h2>Input is Invalid</h2>
    <button @click="confirmError">OK</button>
  </error-alert>
</template>

<script>
import ErrorAlert from "@/components/ErrorAlert.vue";

export default {
  components: {ErrorAlert},
  data(){
    return{
      inputIsInValid:false
    }
  },
  methods:{
    setGoal(){
      const enteredValue = this.$refs.goal.value
      if(enteredValue === ""){
        this.inputIsInValid=true
      }
    },
    confirmError(){
      this.inputIsInValid=false
    }
  }
}
</script>
  • 아주 간단한 예졔 코드를 만들었다.
  1. 가장 윗줄부터 input은 v-model을 써도 되지만 그것이 주가 아니기에 편한 ref를 사용하여 처리하였다.

  2. button들의 @click 메서드들은 data prop의 input is invalid를 true, false 바꿔주는 것으로 만들었다.

  3. 커스텀 컴포넌트는 v-if 속성을 사용하여 유효성에 의존성을 걸어두었다.

자 여기까기 구현을 간단하게 하였는데 무엇이 문제일까? 바로 웹 표준이다.

  • 보면 h2, input, button, dialog 태그가 모두 같은 위치에 있는데 이는 시맨틱 관점과 HTML 관점에서 다이얼로그 요소를 이 위치에 놓는 것은 다이얼로그가 전체 페이지에 오버레이된다는 문제가 있다.

  • 또 이 다이얼로그를 여기에 놓는 것은 HTML 측면에서 이상적이지 않다. 작동은 하지만 접근성을 생각해보면 이상하다.
    또한 스타일링 문제가 발생할 수도 있다.
    따라서 적합한 위치는 DOM Tree 의 root node에 위치하는 것이 적합하다고 볼 수 있다. 그러다면 어떻게 할까?

Teleport

  • react의 createportal 포지션으로, 시맨틱 측면의 이유와 부분적으로는 접근성을 위한 이유 때문에 사용하면 좋다.
...
  <teleport to="body">
    <error-alert v-if="inputIsInValid">
      <h2>Input is Invalid</h2>
      <button @click="confirmError">OK</button>
    </error-alert>
  </teleport>
...
  • 텔레포트는 to라는 한 가지 속성을 필요로 한다. 여기에 CSS 선택자를 넣어서 전체 페이지에서 HTML 요소를 선택한다.

  • 하지만 논리상 여전히 해당 컴포넌트에 속하며 사용된 컴포넌트에서 methods와 상호작용할 수 있지만 DOM 구조 내 다른 곳에서 렌더링 된다.

Fragment

  • react에서 보던 그아이가 맞고 Vue2 까지만 해도 react와 동일하게 1개의 element만 반환했어야했다.

  • 그런데 Vue3로 넘어오고서 지금은 원하는 만큼 많은 상위 레벨의 요소를 가질 수 있다.

  • 시맨틱 또는 스타일링 목적을 제외하면 하나만 유지할 필요가 없다.
    이 기능을 Fragments라고 한다.

이제는 Fragment를 통해 복수의 상위 레벨 요소를 가질 수 있다.

profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글