IT/언어

[Vue.js/Vuetify] v-slot:activator="{ on, attrs }"에 대해 이해하기

개발자 두더지 2023. 4. 19. 21:27
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

 

slot이란?


 어제 포스팅에서 이미 설명한 내용이지만, 한번 더 복습하는 의미에서 한 번 더 확인해보고자한다.

 slot은 부모 컴포넌트에서 자식 컴포넌트로 사용할 컴포넌트를 전달할 수 있는 Vue의 기능이다. 가벼운 예제로 살펴보자.

<!-- parent-component.vue -->
<div>
    <child-component>
    Hello World
    </child-component>
</div>

<!-- child-component.vue -->
<div>
  message: <slot></slot>
</div>

 message: Hello World가 표시된다. 

 그리고 스코프가 있는 슬롯은 자식 컴포넌트가 가지고 있는 속성을 부모 컴포넌트의 slot 부분에서 참조할 수 있게 된다.

<!-- parent-component.vue -->
<template>
  <div>
    <MyCom v-slot:bind-user="parentComponentUser">
      {{ parentComponentUser.user.name }}
    </MyCom>
  </div>
</template>
<script>
import MyCom from '../components/MyCom.vue'
export default {
  components: {
    ChildComponet
  }
}
</script>

<!-- child-component.vue -->
<template>
  <div class="mycom">
    <p>name:<slot v-bind:bind-user="user">{{ user.age }}</slot></p>
  </div>
</template>
<script>
export default {
  name: 'MyCom',
  data () {
    return {
      user: {
          name: 'sano',
         age: 100
      }
    }
  }
}
</script>

 child-component에서 user이라는 slot을 정의하고 있다. 또한 bind-user에서 리액티브한 오브젝트 user를 바인드 하고 있다.  부모 컴포넌트에서는 bind-user이 parentComponentUser에 전달되어 최종적으로는 sano가 표시되게 된다.

 위의 slot의 예와 동일하게 Vuetify의 컴포넌트는 그 컴포넌트에 이벤트가 발생했을 때에 표시되는 컨텐츠를 slot을 사용하여 전달할 수 있다. 

<v-tooltip bottom>
  <!-- slot시작-->
  <template v-slot:activator="{ on, attrs }">
     <v-btn
       color="primary"dark
       v-bind="attrs"v-on="on">
      Button
     </v-btn>
  </template>
  <!-- slot종료-->
  <span>Tooltip</span>
</v-tooltip>

 tooltip의 샘플 코드로 다음의 것들을 알 수 있다.

  • v-tooltip 컴포넌트에는 activator이라는 이름의 slot이 준비되어 있다. v-tooltip컴포넌트는 on, attrs이라는 이름의 속성을 가지고 있다.

 

 

on이란?


 문서에서는 이벤트 핸들러를 가진 오브젝트로 설명하고 있다.

on: { [eventName]: eventHandler },

 실제로 테스트해보자.

<v-tooltip bottom>
  <template #activator="{ on, attrs }">
    <v-btn color="primary" dark v-bind="attrs" v-on="on" @click="clickOn(on)"> Button </v-btn>   
  </template>
  <span>Tooltip</span>
</v-tooltip>

<script>
export default defineComponent({
  setup() {
    const clickOn = (on: any) => {
      console.log(on)
    }
    return {clickOn}
  }
})
</script>

 Button을 클릭하면 console에 이벤드 핸들러를 가진 오브젝트가 표시된다.

 

 

v-on = "on"이란?


v-on="{ [eventName]: eventHandler }” 과 같이 이벤트명과 이벤트 핸들러를 설정한 것이다. 방금의 console.log에서 확인한 Vuetify가 제공하는 이벤트 핸들러가 등록되어 있다. 

 

 

v-bind = "attrs"


 atts는 접근성관련 오브젝트이다.  예제로 살펴보자. 

 Vuetify에는 v-dialog이라는 다이어로그를 구현하기 위한 컴포넌트가 존재하며, 구현의 예로써 공식 페이지에는 아래의 코드가 기재되어 있다.

<template>
  <div class="text-center">
    <v-dialog
      v-model="dialog"
      width="500"
    >
      <template v-slot:activator="{ on, attrs }">
        <v-btn
          color="red lighten-2"
          dark
          v-bind="attrs"
          v-on="on"
        >
          Click Me
        </v-btn>
      </template>

      <v-card>
        <v-card-title class="text-h5 grey lighten-2">
          Privacy Policy
        </v-card-title>

        <v-card-text>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        </v-card-text>

        <v-divider></v-divider>

        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn
            color="primary"
            text
            @click="dialog = false"
          >
            I accept
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        dialog: false,
      }
    },
  }
</script>

 v-dialog의 activator 슬롯에 v-btn을 부여해 슬롯 속성에서는 on 속성 및 attrs 속성을 꺼내고 있다. 이 on 속성은 이벤트 핸들러가 있어, v-btn의 v-on 속성을 부여하는 것으로 화면 버튼을 클릭하면 대화상자가 표시된다.

 그러면 attrs 속성은 무엇일까?  대화상자 전개의 위한 트리거가 되는 컴포넌트에 지정해야할 WAI-ARIA속성인 것 같다. 실제 v-dialog의 activator 슬롯에는 버튼이 바인드 되어있는 attrs에는 대화상자가 닫혀 있는 상태에서는 다음의 오브젝트가 들어 있다.

{
  "role": "button",
  "aria-haspopup": true,
  "aria-expanded": false
}

 aria-expanded 속성은 대화상자를 전개하면 true가 된다. 

Vuetify에서는 이러한 속성을 부여하기 쉬우며 접근성을 담보하기 쉽도록 되어 있다. 물론 바인드 대상에 따라 role은 바뀌지 않는다. div나 input에 바인드해도 role은 button 그대로이다.

 

 

value: boolean


 문서에는 명확히 기재되어 있지 않지만 이벤트 핸들러가 호출됐는지에 대한 정보인 것 같다. 

 value와 on을 이용해서 icon에 마우스 오버하면 tooltip이 표시되는 동시에 icon의 색을 변경시킬 수 있다.

<v-tooltip bottom>
  <template #activator="{ on, attrs, value }">
    <v-icon
      medium
      class="ml-1"
      :color="value ? '#0068B7' : '#757575'"
      v-bind="attrs"
      v-on="on"
    >
      mdi-help-circle
    </v-icon>
  </template>
 thipに出るテキスト       
</v-tooltip>


참고자료

https://qiita.com/Gedyra/items/9d05e10329808367396f

https://mashoo1101.hatenablog.com/entry/2022/03/05/172305

728x90