Heim  >  Fragen und Antworten  >  Hauptteil

Gibt es in Vue 3 keine Möglichkeit, Slot-Inhalte zuverlässig zu verarbeiten?

<p>Ich migriere derzeit eine Vue 2-Codebasis auf Vue 3. </p> <pre class="brush:php;toolbar:false;"><card> <template #default> <card-header> <title level="3">Header</title> </card-header> <Kartenkörper v-for="b in bodyCount" :key="'b' + b"> Körper {{ b }} </card-body> <Kartenfußzeile v-for="f in footerCount" :key="'f' + f"> <text>Fußzeile {{ f }}</text> </card-footer> </template> </card></pre> <p>Die Kartenkomponente verfügt über eine Renderfunktion, die <code>this.$slots.default()</code> aufruft. Allerdings werden in Vue 3 dadurch andere Inhalte zurückgegeben als in Vue 2. Wenn ich also <code>console.log(this.$slots.default())</code> mache, erhalte ich ein Array mit 3 Elementen, [v-Knoten vom Typ „Header“, Typ Es ist ein v-Knoten von Symbol(Fragment), ein V-Knoten vom Typ Symbol(Fragment)]</p> <p>Genauer gesagt erkennt es den Kartenfuß/den Kartenkörper nicht als Komponenten, stattdessen sehe ich das Symbol (Fragment) im Typ. Der Card-Header ist eigentlich in Ordnung, da er sich nicht in der V-for-Schleife befindet. </p> <p>In der Rendering-Funktion der Kartenkomponente gibt es eine Logik, die wissen muss, wie viele Text-/Fußzeilenkomponenten sie hat. Ich muss also in der Lage sein, den Komponententyp zu erkennen. Ist das in Vue 3 nicht möglich? Ich vermute, dass dies etwas mit dem V-for hier zu tun hat, aber ich bin mir nicht sicher, wie ich die endgültigen V-Knoten tatsächlich erhalten soll. In diesem Beispiel möchte ich, dass das Array anstelle von 3 Elementen den Kartenkopf + alle Kartenkörper + alle Kartenfußzeilen enthält. </p>
P粉714844743P粉714844743416 Tage vor390

Antworte allen(2)Ich werde antworten

  • P粉865900994

    P粉8659009942023-08-31 00:54:26

    你的卡片组件的设计对我来说看起来没有意义。我建议你重新考虑一下。

    这是简单的游乐场渲染槽

    const { createApp, h } = Vue;
    
    const Card = {
      setup(props, { attrs, slots, emit, expose }) {
          return () => [           
              h('label', 'Card'),
              h('div', 'Slots:'),
              h('div', {}, slots.default()),
              h('div', {}, slots.header()),
              h('div', {}, slots.body()),
              h('div', {}, slots.footer())
          ]
      }
    }
    
    const App = { 
      components: { Card },
      data() {
        return {
        }  
      }
    }
    const app = createApp(App)
    app.mount('#app')
    #app { line-height: 2; }
    [v-cloak] { display: none; }
    label { font-weight: bold; }
    <div id="app">
    <card>
        <template #default>
           Default
            <card-header>
                <title level="3">Header</title>
            </card-header>
        </template>
        <template #header>
           Header
        </template>
        <template #body>
           Body
        </template>
        <template #footer>
           Footer
        </template>
    </card>
    </div>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

    请注意警告。 Vue 不会在此处渲染 card-header,因为它无法解析它。

    [Vue warn]: Failed to resolve component: card-header
    If this is a native custom elemen

    如果您可以访问数据,为什么要通过slots操作card-body/card-footer项目直接通过bodyCount

    如果对我来说看起来不合理。

    const { createApp, h } = Vue;
    
    const CardHeader = {
        template: '<div class="card-header">card-header: <slot></slot></div>'
    }
    const CardBody = {
        template: '<div class="card-body">card-body: <slot></slot></div>'
    }
    const CardFooter = {
        template: '<div class="card-footer">card-footer: <slot></slot></div>'
    }
    
    const Card = {
      components: {
        CardHeader, CardBody, CardFooter
      },
      setup(props, { attrs, slots, emit, expose }) {
          //console.log(slots.default())
          return () => [           
              h('label', 'Card'),
              h('div', 'Slots:'),
              h('div', {}, slots.default()),
          ]
      }
    }
    
    const App = { 
      components: { Card, CardHeader, CardBody, CardFooter },
      data() {
        return {
          bodyCount: ['a','b'],
          footerCount: ['a','b']
        }  
      }
    }
    const app = createApp(App)
    app.mount('#app')
    #app { line-height: 2; }
    [v-cloak] { display: none; }
    label { font-weight: bold; }
    .card-header, .card-body, .card-footer {
      border: 1px solid #F0F0F0;
    }
    <div id="app">
    <card>
        <template #default>
            <card-header>
                <div level="3">Header</div>
            </card-header>
            bodyCount: {{bodyCount.length}}
            <card-body
                v-for="b in bodyCount"
                :key="'b' + b">
                Body {{ b }}
            </card-body>
            footerCount: {{footerCount.length}}
            <card-footer
                v-for="f in footerCount"
                :key="'f' + f">
                <text>Footer {{ f }}</text>
            </card-footer>
        </template>
    </card>
    </div>
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

    Antwort
    0
  • P粉440453689

    P粉4404536892023-08-31 00:37:50

    事实证明 - 可以通过数组每个元素上的 Children 属性来展开片段。因此,在这种情况下,v-for 会生成一个 v 节点,它是一个片段,但我们可以通过查看 Children 属性来推断更多内容。

    Antwort
    0
  • StornierenAntwort