簡體   English   中英

Vue 里有 React.Fragment 之類的東西嗎?

[英]Is there something like React.Fragment in Vue?

在 React 中我可以做這樣的事情:

// parent component
export default (){
  return (
     <div>
       <div>1</div>
       <ChildComponent />
       <div>5</div>
     </div>
  );
}

// child component
export default (){
  return (
     <React.Fragment>
       <div>2</div>
       <div>3</div>
       <div>4</div>
     </React.Fragment>
  );
};

// compiled html tags in browser .
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>

但是在 Vue 中,當我做同樣的事情時,事情就不同了。

// parent component
<template>
    <div>
        <div>1</div>
        <child-component />
        <div>5</div>
    </div>
</template>

<script>
    import childComponent from 'path/to/childComponent';
    export default {
      components: { childComponent }
    }
</script>
-------------------------------------------------------------
// child component
<template>
    <div id='have_to_write_in_vue'>
        <div>2</div>
        <div>3</div>
        <div>4</div>
    <div>
</template>

// compiled html tags in browser .
<div>1</div>
<div id='have_to_write_in_vue'>
    <div>2</div>
    <div>3</div>
    <div>4</div>
</div>
<div>5</div>

不同之處在於,'DIV' 標簽在 Vue 中不在同一級別。 我該如何處理?

我問這是因為出現無用的嵌套時出了點問題。

Vue 2

Vue-fragment包為 vue 2 提供了無根組件。

視圖 3

Vue 3 正式支持多根節點組件(片段) https://v3-migration.vuejs.org/new/fragments.html

Vue 中缺少第一方 Fragment 組件讓我抓狂!

我看過vue-fragment npm 包,但它讓我對他們做了多少感到緊張,並且覺得必須有更好的方法。

我想出了一些非常輕量級的東西......它之所以有效,是因為允許功能組件返回多個根節點。

然而,這不像 Reacts 那樣 100% 有效。 例如,在 React 中,您實際上可以使用React.Fragment作為應用程序中的根節點。 當您已經在一個組件中時,這似乎僅在 Vue 中有效(即:它不能是您的基本組件的根節點)。

const Fragment = {
  functional: true,
  render: (h, ctx) => ctx.children
}

使用它...

<Fragment>
  <div>Div 1</div>
  <div>Div 2</div>
</Fragment>

超級好用...

{someCondition && (
  <Fragment>
    <div>yay i can use multiple nodes</div>
    <div>:)</div>
  </Fragment>
)}

<div>
  Some inline text {condition ? (
    <Fragment>now I can use <strong>html</strong> and {variables}</Fragment>
  ) : (
    <Fragment>So many possibilities</Fragment>
  )}
</div>

顯然,Vue.js v3 現在支持開箱即用的片段:片段(Vue.js 文檔)

Vue v3

這是對@Roi 對 Vue v3 的回答的簡單改編。

正如@dakujem 提到的,Vue v3 支持開箱即用的多根組件。 但是它不支持深度嵌套的片段。

更新:您可以嵌套<template>


<template>
  <div>
    <ul>
      <li>A</li>
      <li>B</li>
      <template>
        <li>C</li>
        <li>D</li>
      </template>
    </ul>
  </div>
</template>

找到了這個很棒的指令,並且經過了實戰考驗! https://github.com/privatenumber/vue-frag

<template>
    <div v-frag> <!-- This element will be unwrapped -->

        <div v-for="i in 10">
            {{ i }}
        </div>
    </div>
</template>

<script>
import frag from 'vue-frag';

export default {
    directives: {
        frag
    }
};
</script>

從自述文件:

這與 vue-fragment 有什么不同?

它們都旨在做同樣的事情。 但是,vue-fragment 是一個組件,而 vue-frag 是一個指令。 當我看到 vue-fragment 沒有任何測試來確保正確的行為,有很多無人看管的問題,並且似乎沒有積極維護時,我做了 vue-frag。 就大小而言,它們都很小,但 vue-frag 略小(993B vs 798B)。

對於使用 Vue 3 + JSX/TSX 的用戶,您可以執行以下任一操作:

<>
  <p>one</p>
  <p>two</p>
</>

或者

import { Fragment } from 'vue';

<Fragment>
  <p>one</p>
  <p>two</p>
</Fragment>

注意:我使用@vue/babel-plugin-jsx來支持 JSX/TSX。

TLDR:創建一個組件Frag.vue

<template>
    <slot></slot>
</template>

正如其他答案中提到的,您可以嵌套template s,但需要注意:

你可以做v-if

<template>
  <ul>
    <li>
      first
    </li>
    <template v-if="true">
      <li>
        second
      </li>
      <li>
        third
      </li>
    </template>
    <li>
      fourth
    </li>
  </ul>
</template>

生產:

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
  <li>fourth</li>
</ul>

v-for

<template>
  <ul>
    <li>
      first
    </li>
    <template v-for="i in list">
      <li>
        second {{i}}
      </li>
      <li>
        third {{i}}
      </li>
    </template>
    <li>
      fourth
    </li>
  </ul>
</template>

生產:

<ul>
  <li>first</li>
  <li>second 0</li>
  <li>third 0</li>
  <li>second 1</li>
  <li>third 1</li>
  <li>fourth</li>
</ul>

但是,如果沒有v-forv-if

<template>
  <ul>
    <li>
      first
    </li>
    <template>
      <li>
        second
      </li>
      <li>
        third
      </li>
    </template>
    <li>
      fourth
    </li>
  </ul>
</template>

它產生

<ul>
  <li>first</li>
  <li>fourth</li>
</ul>

您可以通過始終使用v-if="true來解決它,但它不太理想。

話雖如此,因為模板中的插槽將所有傳遞的子項分散到默認插槽中,您可以創建一個非常簡單的組件:

<template>
    <slot></slot>
</template>

而已。 將其命名為Frag.vue ,在需要的地方導入它。 您可以將它與v-ifv-for一起使用,也可以兩者都不使用。

<template>
  <ul>
    <li>
      first
    </li>
    <Frag v-if="true">
      <li>
        second (v-if)
      </li>
      <li>
        third (v-if)
      </li>
    </Frag>
    <Frag v-for="i in list">
      <li>
        second {{i}} (v-for)
      </li>
      <li>
        third {{i}} (v-for)
      </li>
    </Frag>
    <Frag>
      <li>
        second (nothing)
      </li>
      <li>
        third (nothing)
      </li>
    </Frag>
    <li>
      fourth
    </li>
  </ul>
</template>

生產:

<ul>
  <li>
    first
  </li>
  <li>
    second (v-if)
  </li>
  <li>
    third (v-if)
  </li>
  <li>
    second 0 (v-for)
  </li>
  <li>
    third 0 (v-for)
  </li>
  <li>
    second 1 (v-for)
  </li>
  <li>
    third 1 (v-for)
  </li>
  <li>
    second (nothing)
  </li>
  <li>
    third (nothing)
  </li>
  <li>
    fourth
  </li>
</ul>

只需使用嵌套template標簽來包裝多個子 Vue 組件。

<template>
  <template>
    <div class="my-first-child"></div>
    <div class="my-second-child"></div>
    <div class="my-third-child"></div>
  </template>
</template>

這將導致

<div class="my-first-child"></div>
<div class="my-second-child"></div>
<div class="my-third-child"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM