【问题标题】:Is there something like React.Fragment in Vue?Vue 中有类似 React.Fragment 的东西吗?
【发布时间】:2020-04-10 19:39:08
【问题描述】:

在 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 中不在同一级别。 我该如何处理?

我问这是因为出现无用嵌套时出了点问题。

【问题讨论】:

  • 有类似的,请查看this github。这可能是几个模块之一。

标签: reactjs vue.js fragment


【解决方案1】:

Vue 2

Vue-fragment 为 vue 2 提供了无根组件。

Vue 3

Vue 3 正式支持多根节点组件(片段) https://v3.vuejs.org/guide/migration/fragments.html

【讨论】:

    【解决方案2】:

    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>
    

    【讨论】:

    • 这看起来不错。你能解释一下你是如何实现这个 Fragment 组件的吗?
    • 它是一个使用ctx.children的功能组件。 Vue 功能组件允许多个根节点。功能组件的代码在答案const Fragment = {...}
    • 好的,谢谢。但遗憾的是,我收到一条错误消息,上面写着“[Vue 警告]:从渲染函数返回多个根节点。渲染函数应该返回一个根节点。”在 Vue v2.6.11 上
    • 你添加functional: true了吗?
    • @Roi 即使是functional: true
    【解决方案3】:

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

    【讨论】:

    • Vue 一直支持嵌套&lt;template&gt;s,它们的工作方式与&lt;React.fragment&gt;s 一样。这不是 v3 中添加的东西。 v2 和 v3 之间的唯一区别是,在 v2 中,组件的根 &lt;template&gt; 必须限制为只有 1 个子级。现在这个限制已经消失了,代价是不再有$el。现在,如果您想要模板中的任何 DOM 元素,您必须使用 $ref
    • 真的,感谢您的更新。这里我的意思是多根片段,这是 v3 中的新内容。在 React 中,您将使用 &lt;React.Fragment&gt;(或 &lt;&gt;&lt;/&gt;)来克服单根限制,我认为这是 OP 要求的。
    【解决方案4】:

    Vue v3

    这是对@Roi 对 Vue v3 的回答的简单改编。

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

    更新:你可以嵌套&lt;template&gt;

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

    【讨论】:

    【解决方案5】:

    发现了这个很棒的指令并且经过了实战考验! 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)。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

      • Module '"../../node_modules/vue/dist/vue"' has no exported member 'Fragment'
      【解决方案7】:

      只需使用嵌套的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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-04
        • 2012-05-31
        • 2012-11-27
        • 2017-11-21
        • 2012-08-03
        • 2015-08-25
        • 1970-01-01
        • 2015-11-14
        相关资源
        最近更新 更多