Vue.js의 inheritAttrs에 대한 큰 착각

소개



Vue 구성 요소에는 inheritAttrs라는 지시문이 있습니다.
  • API — Vue.js #inheritAttrs

  • 직역하면 「속성을 계승한다」.

    우선 간단한 예를 나타냅니다. Vuetify.jsv-btn 을 래핑한 버튼을 만들어 봅시다.
  • 클릭하면 사라지는 DismissibleButton 를 만듭니다.
  • 소멸하기까지의 시간을 밀리 세컨드로 timeout 로 지정할 수 있도록 합니다.

  • DismissibleButton.vue
    <template>
      <v-btn v-if="visible" @click="hide">
        <slot />
      </v-btn>
    </template>
    
    <script>
      export default {
        props: {
          timeout: {
            type: Number,
            default: 0,
          },
        },
        data() {
          return {
            visible: true,
          };
        },
        methods: {
          hide() {
            setTimeout(() => {
              this.visible = false;
            }, this.timeout);
          },
        },
      };
    </script>
    

    사용측
    <dismissible-button :timeout="1000">Click Me</dismissible-button>
    
  • 슬롯으로 버튼 텍스트를 받고 그대로 <v-btn>로 옮깁니다.
  • 가시성의 제어를 더하는 약간의 구현을 썼습니다.

  • inheritAttrs 동작



    그럼 여기서,

    "<v-btn>to 속성과 nuxt 속성을 전달하고 싶다!"

    라는 요구가 발생했다고 합니다.
  • Nuxt × Vuetify 상황에서 v-btn을 nuxt-link로 사용하고 싶다 - Qiita

  • 여기에 나열된 솔루션의
    <v-btn to="/path/to/link" nuxt>リンク</v-btn>
    

    이것이군요. 이것을 랩한 <dismissible-button> 에 있어서, 가능한 한 재이용성이 높은 형태로 <v-btn> 에 받아들입니다.
    <dismissible-button :timeout="1000" to="/path/to/link" nuxt>リンク</dismissible-button>
    

    이러한 사용법을 생각합니다.

    true일 때 (기본값)



    아무것도 지정하지 않은 경우에는 적용됩니다.
  • Vue.js의 $attrs 및 inheritAttrs - isoppp.com

  • 위의 경우 component B가 확장되면
    <div color="red" type="number">{ color: 'red', type: 'number' }</div>
    

    라는 html을 출력합니다.

    component B 에 props 가 정의되어 있지 않은 속성을 주면(자) 디폴트에서는 생성되는 루트의 요소에 속성이 추가됩니다.

    이것을 읽은 저는 이런 렌더링 결과를 기대했습니다.
    <v-btn> 가 컴퍼넌트의 루트 요소이기 때문에, 마음대로 거기에 이어 준다! ! !

    그리고.

    예상 결과
    <template>
      <v-btn v-if="visible" @click="hide" :to="to" :nuxt="nuxt">
        <slot />
      </v-btn>
    </template>
    

    그렇지만 실제로는 거기에 전개되지 않고, 무려 <v-btn> 보다 더욱 아래의 HTML 요소의 <button> 에 건너고 있었습니다…

    실제 결과
    <button to="/path/to/link" nuxt=""></button>
    

    이런 거야…
    (이 그림을 눈에 굽고 돌아가십시오)



    단적으로 말로 표현하면

    inheritAttrs 로 하위 컴포넌트에 흘리면 『 props
    그렇게 됩니다. 이것은 첫 견해입니다 ...

    $props일 때


    $attrs 그렇게 하면 암시적 인수는 이루어지지 않습니다. 명시적으로 false 로 받아들인 경우는 inheritAttrs: false 에 흘릴지 어떨지의 판정이 행해집니다만, 스스로 그 처리를 써야 합니다.

    DismissibleButton.vue
    <template>
      <v-btn v-if="visible" @click="hide" v-bind="$attrs"> <!-- ← これを追加! -->
        <slot />
      </v-btn>
    </template>
    
    <script>
      export default {
        inheritAttrs: false, // ← これを追加!
        props: {
          timeout: {
            type: Number,
            default: 0,
          },
        },
        data() {
          return {
            visible: true,
          };
        },
        methods: {
          hide() {
            setTimeout(() => {
              this.visible = false;
            }, this.timeout);
          },
        },
      };
    </script>
    
    v-bind 에 관해서 설명하면, 이하의 2 개의 기술은 등가가 됩니다.
    <v-btn v-if="visible" @click="hide" v-bind="$attrs">
    
    <v-btn v-if="visible" @click="hide" :to="$attrs.to" :nuxt="$attrs.nuxt">
    

    실제로는 $props 는 이것에 한정되지 않기 때문에, 수가 증가해도 자동적으로 모두 수류된다 v-bind="$attrs" 가 우수하다고 말할 수 있겠네요.

    요약



    중요한 일이므로 다시. `
  • $attrs 는 모두 v-bind="$attrs"
  • 명시적으로 inheritAttrs 로 흘리면 $attrsv-bind="$attrs" 의 분배가 행해진다

  • 기본적으로 $props 에는 별로 의지하지 않는 편이 좋은 것일지도 모르겠네요…

    좋은 웹페이지 즐겨찾기