如果我们试图创建一个没有根节点的 vue 模板, 比如这样:
Node 1
Node 2
我们就会收到编译或运行时错误, 因为模板必须具有单个根元素.
通常, 我们通过在最外层包裹一层 div 来解决这个问题, 但这个 div 元素一般没有啥使用, 就是让模板符合单根需求.
Node 1
Node 2
这样的方式通常问题不在, 但是在某些情况下, 拥有多根模板是必要的. 在本文中, 我们来探讨一下何时需要以及如何解决多根的问题.
渲染数组
某些情况下, 可能需要组件渲染子节点数组以包含在父组件中.
例如, 一些 CSS 特性需要非常特殊的元素层次结构才能正确工作, 比如 CSS grid 或 flex, 不能在父元素和子元素之间使用包装器.
还有一个问题, 在组件中添加包装元素可能会导致渲染无效的 html. 例如, 如果要构建 table, 则表行必须仅具有用于子项的表单元格.
简而言之, 单根需求意味着在 Vue 中将无法返回子元素的组件的设计模式.
Fragments
这个单根限制对于 React 也是一个问题, 但是它在版本 16 中提供了一个称为 [fragments][1] 的功能. 要使用它, 只需要将多根模板包装在特殊的 React.Fragment 元素中:
这将使子组件没有多余包装, 还有一个简洁的短语法<>:
Vue 中的 Fragments
那么 Vue 是否也会引入 fragments? 这可能不会很快, 原因是虚拟 DOM 差异算法依赖于具有单个根的组件. 根据 Vue 贡献者 Linus Borg 的说法:
“允许 fragments 需要对 [diffing] 算法进行重大更改… 不仅要使其能够正常工作,而且还必须使其具有高性能。… 这是一项非常繁重的任务” |
具有渲染功能的函数组件
函数组件没有单根限制, 因为它们不需要像有状态组件那样在虚拟 DOM 中进行区分. 这意味着, 如果组件只需要返回静态 HTML, 那么拥有多个根节点也没什么问题.
还有一个警告: 我们需要使用渲染功能, 因为 vue-loader 当前不支持多根功能([尽管对此进行了讨论][2]).
使用指令技巧
还可以使用一种简单的方法来绕过单根限制. 就是使用自定义指令, 首先我们先所包裹的元素删除
之前的:
中间步骤:
最终:
要使它正常工作有点棘手, 这里可以使用由 Julien Barbay 写的 [vue-fragments][3] 的插件.
vue-fragments
vue-fragments 可以作为一个插件安装到你的 Vue 项目中
- import {
- Plugin
- } from "vue-fragments";
- Vue.use(Plugin);
该插件注册了一个全局 VFragment 组件, 将其用作组件模板中的包装器, 类似于 React 片段的语法:
- Fragment 1
- Fragment 2
我不确定这个插件在所有的用例中有多健壮 -- 它看起来可能是脆弱的 -- 但在我做的实验中, 它工作得很好.
来源: http://developer.51cto.com/art/202003/612107.htm