奇怪的模板和 vue.js 的根节点

Posted

技术标签:

【中文标题】奇怪的模板和 vue.js 的根节点【英文标题】:Oddity with templates and root node with vue.js 【发布时间】:2017-04-17 18:43:08 【问题描述】:

我认为这可能是我偶然发现的错误,不确定。我收到一个组件的 Vue.js 警告:

vue.js:2611 [Vue 警告]:不能使用 <template> 作为组件根元素,因为它可能包含多个节点:

问题似乎是这样的:

<template id="tpl-field">
    <template v-if="fieldType==='checkbox-inline'">
        <label class="checkbox-inline">[SNIP]</label>
    </template>
    <template v-else>
    [SNIP]
    </template>
</template>

所以我有两个模板节点,这似乎是它阻塞的多个节点(当然每个模板节点只包含一个节点)。然而,这是 Vue 中的 if-else - 如果其中一个节点存在,则另一个节点在逻辑上不存在。

这里的问题演示:https://jsfiddle.net/jonmor51/Ldz3k0jp/1/。如果我将所有内容都包装在一个 div 中,它就可以工作。但是没有,它会失败。 (不幸的是,在我想使用它的上下文中,即对于 Bootstrap 网格中的内联复选框,包装在 div 中会破坏事情)。

【问题讨论】:

【参考方案1】:

有用的东西 - 只需使用 div display: contents 作为组件的根,浏览器将忽略该元素并将子元素(可能很多)视为上层 dom 元素的子元素

    <div style="display: contents">
        <template v-if="...">
            <template v-for="..."> ...
        </template>
        <template v-if="...">
        </template>
    </div  

甚至可以在桌子内使用!

【讨论】:

【参考方案2】:

内部templates 直子,是单元素吗?如果是这样,您只需删除内部templates 并将v-if 移动到label

或者,只是使用span 而不是div 作为您的快速修复,这不会破坏内联元素的样式。

【讨论】:

你是对的,这很有趣。如果我将 v-if 和 v-else 移动到包含的元素,则没有问题,即使表面上存在相同的情况(即两个替代根元素,这次是 div 不是模板)。所以看起来它只是导致问题的模板。 jsfiddle.net/jonmor51/Ldz3k0jp/3 @JohnMoore 当我建议删除templates 时我实际上并没有尝试过...所以事实证明vue 可以正确判断v-if 时是否会有一个根元素用来。而template 只是不允许作为 root 用户,vue 直接发出警告,而不分析最终渲染的内容。【参考方案3】:

不确定这是否会解决您的引导问题...但您可以使用 &lt;transition&gt; 标记包装内部模板并为每个模板设置一个键。

请检查这个工作小提琴

https://jsfiddle.net/AldoRomo88/7c7znu3p/

【讨论】:

是的,这似乎很好地完成了这项工作。它也可以在没有“密钥”的情况下完成,那么为什么需要“密钥”呢?我可能会接受这个,即使它有点杂乱无章的感觉(这不是过渡的目的),但它至少让我感动! 我收到警告,但是转换不能与列表一起使用。 ;-) 在我看来 vue.js 开发人员把事情搞砸了。 @Drachenfels 确信这是因为您想同时在转换标记内渲染多个 dom 元素。在应用 v-if else 等条件后,必须只渲染一个元素,或者您需要使用将元素包装在附加标签中的转换组。顺便说一句,这太烦人了:我遇到了问题,几分钟后我考虑使用转换标签,然后出现下一个问题,我意外地找到了上一个任务的解决方案:|

以上是关于奇怪的模板和 vue.js 的根节点的主要内容,如果未能解决你的问题,请参考以下文章

并查集模板

Vue.js 3.0 组件是如何渲染为 DOM 的?

并查集模板

vue3的根节点

当只有一个存在时,Vue.js有多个根节点[重复]

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用