Gibt es in Vue 3 keine Möglichkeit, Slot-Inhalte zuverlässig zu verarbeiten?
P粉714844743
P粉714844743 2023-08-30 08:47:17
0
2
432
<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粉714844743
P粉714844743

Antworte allen(2)
P粉865900994

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

这是简单的游乐场渲染槽

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>
P粉440453689

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

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage