Vue中是否有类似React.Fragment的内容?

gopyfrb3  于 2023-01-02  发布在  Vue.js
关注(0)|答案(8)|浏览(248)

在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中不在同一级别。我该如何处理这个问题?
我问这是因为一些错误时,无用的嵌套出现。

raogr8fs

raogr8fs1#

第2次查看

Vue-fragment促进了vue 2的无根组件。

第3次查看

Vue 3官方支持多根节点组件(片段)https://v3-migration.vuejs.org/new/fragments.html

ukxgm1gy

ukxgm1gy2#

Vue中缺少第一方片段组件让我抓狂!
我看过X1 M0 N1 X NPM包,但它让我对他们做了多少感到紧张,觉得必须有更好的方法。
我想出了一个非常轻量级的东西...它之所以能工作,是因为功能组件被允许返回多个根节点。
但是,这并不像React那样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>
pvcm50d1

pvcm50d13#

显然,Vue.js v3现在支持开箱即用的片段:Fragments (Vue.js documentation)

ppcbkaq5

ppcbkaq54#

Vue版本3

  • 这是@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>
pkmbmrz7

pkmbmrz75#

对于使用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。

sqougxex

sqougxex6#

发现这个令人敬畏的指令,并经过战斗测试! 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片段有何不同?
它们都是为了做同样的事情而设计的。然而,vue-fragment是一个组件,而vue-frag是一个指令。当我看到vue-fragment没有任何测试来确保正确的行为时,我创建了vue-frag。在大小方面,它们都很小,但vue-frag稍小(993B对798B)。

u4vypkhs

u4vypkhs7#

TLDR:创建组件Frag.vue

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

正如在其他答案中提到的,您可以嵌套template,但要注意:
您可以执行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来解决这个问题,但它有点不太理想。
话虽如此,由于模板中的slot将所有传递的子元素都分散到默认slot中,因此可以创建一个非常简单的组件:

<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>
yiytaume

yiytaume8#

只需使用嵌套的template标记来 Package 多个子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>

相关问题