programing

태그를 생략하고 태그의 내용을 렌더링하는 사용자 지정 Vue 지시문을 사용하시겠습니까?

randomtip 2022. 10. 23. 11:53
반응형

태그를 생략하고 태그의 내용을 렌더링하는 사용자 지정 Vue 지시문을 사용하시겠습니까?

커스텀 Vue 디렉티브를 생성하여 태그를 생략하고 디렉티브가 true일 때 태그의 내용을 렌더링하고 싶습니다.

예를 들어 vue 인스턴스의 데이터가 다음과 같이 정의되어 있는 경우

 data:{
    omitIt: true
 }

마크업이 다음과 같은 경우:

 <div v-omit="omitIt" class="someClass">
      Hello world!
 </div>

언제omitIt위와 같이 false로 설정되어 있습니다.다음 항목을 돔에 렌더링합니다.

<div class="someClass">
      Hello world!
 </div>

하지만 언제omitIt맞아요. 다음 것만 돔으로 만들고 싶어요

Hello world!

처음에 이 문제를 해결하려고 했던 것은 다음과 같습니다(커스텀 vue 디렉티브는 아닙니다).

 <template v-if="!omitIt">
      <div class="someClass">
  </template>
  Hello world!
  <template v-if="!omitIt">
      </div>
  </template>

위는 예쁘지 않지만 잘 될 것 같아서요.하지만 아아, 무엇이 돔으로 만들어졌는가?omitItfalse는 다음과 같습니다.

 <div class="someClass"></div>
 Hello world!

원하는 결과를 얻을 수 있는 방법이 있나요?

@Nit의 답변은 훌륭하고 단순한 답변이라고 생각하고 업베이트를 했습니다만, 1개의 결점이 있습니다.슬롯이 루트 요소가 아닐 수 있기 때문에 래퍼를 생략할 필요가 있을 때 컴포넌트가 실패합니다.이는 슬롯에 여러 요소를 포함할 수 있으며 슬롯에 여러 개의 요소가 포함되어 있는 경우 루트 요소가 여러 개 존재할 수 있기 때문입니다.이러한 요소는 허용되지 않습니다.

컴포넌트가 랩되지 않으면 슬롯의 첫 번째 요소만 렌더링하는 부분 솔루션이 있습니다.

Vue.component("wrapper", {
  props:{
    nowrap: {type: Boolean, default: false}
  },
  render(h){
    // This will *only* render the *first* element contained in 
    // the default slot if `nowrap` is set. This is because a component
    // *must* have a single root element
    if (this.nowrap) return this.$slots.default[0]
    // Otherwise, wrap the contents in a DIV and render the contents
    return h('div', this.$slots.default)
  }
})

여기 그것이 작동하는 예가 있습니다.

console.clear()

Vue.component("wrapper", {
  props:{
    nowrap: {type: Boolean, default: false}
  },
  render(h){
    // Log a warning if content is being omitted
    const omissionMessage = "Wrapper component contains more than one root node with nowrap specified. Only the first node will be rendered."
    if (this.$slots.default.length > 1 && this.nowrap)
      console.warn(omissionMessage)
    
    // This will *only* render the *first* element contained in 
    // the default slot if `nowrap` is set. This is because a component
    // *must* have a single root element
    if (this.nowrap) return this.$slots.default[0]
    
    // Otherwise, wrap the contents in a DIV and render the contents
    return h('div', this.$slots.default)
  }
})

new Vue({
  el: "#app"
})
.someClass{
  color: blue
}
<script src="https://unpkg.com/vue@2.4.2"></script>
<div id="app">
  <wrapper class="someClass">Hello World</wrapper>
  <wrapper nowrap>No wrap, single root</wrapper> <br>
  <wrapper nowrap>
    No wrap, two roots. Paragraph is ommitted.
    <p>Some other content</p>
  </wrapper>
</div>

몇 가지 주의:컴포넌트는 다음 항목을 추가하지 않으면 항상 랩됩니다.nowrap아트리뷰트로서또한 클래스는 소품으로 지정하지 않고 포장된 용기에 추가됩니다.이는 사용자가 지정하지 않는 한 Vue가 컴포넌트의 루트 요소에 소품으로 지정되지 않은 속성을 자동으로 렌더링하기 때문입니다.

이 답은 틀렸습니다.슬롯을 이렇게 사용할 수 없습니다.대신 Bert의 답변을 봐주세요.


가장 쉬운 해결책은 슬롯이 있는 래퍼 컴포넌트를 만들고 생략 인수를 받침으로 전달하는 것입니다.
컨텐츠 배포 부분은 비교적 간단해집니다.

래퍼 컴포넌트 템플릿:

<slot v-if="omitIt"></slot>
<div v-else>
  <slot></slot>
</div>

래퍼를 사용하는 장소:

<wrapper v-bind:omitIt="omitIt">
  // Content
</wrapper>

언급URL : https://stackoverflow.com/questions/46201768/custom-vue-directive-to-omit-tag-but-render-tags-contents

반응형