New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[vue] vue为什么要求组件模板只能有一个根元素? #457
Comments
因为"树"状数据结构,肯定要有个"根",一个遍历起始点吧,我是这么理解的。 |
我是在知乎上看到的这个问题,转念一想,用了大半年的vue,好像真的没有了解过: ‘为什么只能有且只有一个根元素’ 于是我花了二十多分钟去找了一下答案......竟然没有找到答案.... 好的现在我来说说我的理解,如果有不对的地方欢迎指出。 我觉得这个问题需要从两个方面来说起: 1.new Vue({el:'#app'}) 2.单文件组件中,template下的元素div 一、 当我们实例化Vue的时候,填写一个el选项,来指定我们的SPA入口:
同时我们也会在body里面新增一个id为app的div
这很好理解,就是为vue开启一个入口,那我们不妨来想想,如果我在body下这样
Vue其实并不知道哪一个才是我们的入口,因为对于一个入口来讲,这个入口就是一个‘Vue类’,Vue需要把这个入口里面的所有东西拿来渲染,处理,最后再重新插入到dom中。 二、 当我们在webpack搭建的vue开发环境下,使用单文件组件时,你可能会这样:
那这里为什么template下也必须有且只能有一个div呢? 这里我们要先看一看template这个标签,这个标签是HTML5出来的新标签,它有三个特性: 1.隐藏性:该标签不会显示在页面的任何地方,即便里面有多少内容,它永远都是隐藏的状态; 2.任意性:该标签可以写在页面的任何地方,甚至是head、body、sciprt标签内; 3.无效性:该标签里的任何HTML内容都是无效的,不会起任何作用; 但是呢,你可以通过innerHTML来获取到里面的内容。 知道了这个,我们再来看.vue的单文件组件。其实本质上,一个单文件组件,本质上(我认为)会被各种各样的loader处理成为.js文件(因为当你import一个单文件组件并打印出来的时候,是一个vue实例),通过template的任意性我们知道,template包裹的HTML可以写在任何地方,那么对于一个.vue来讲,这个template里面的内容就是会被vue处理为虚拟dom并渲染的内容,导致结果又回到了开始 :既然一个.vue单文件组件是一个vue实例,那么这个实例的入口在哪里? 如果在template下有多个div,那么该如何指定这个vue实例的根入口? 通过这个‘根节点’,来递归遍历整个vue‘树’下的所有节点,并处理为vdom,最后再渲染成真正的HTML,插入在正确的位置 那么这个入口,就是这个树的‘根’,各个子元素,子组件,就是这个树的‘枝叶’,而自然而然地,这棵‘树’,就是指一个vue实例了。 如有错误,欢迎讨论~ |
官方其实有解释。 |
谢谢楼上两位兄弟的答案,都很有参考价值 |
有点疑惑,Vue 1.x的时候是允许有多个根元素的,难道那时候没有vdom么? |
@PanJiaChen 活捉大佬! |
VDOM是vue2.0新增的 |
我觉得这个问题可以抽象为:逻辑抽象树为什么只能有一个根 从效率上,如果多个根,那么就会产生多个入口(遍历、查找)从效率上来说都不方便 其次,如果一颗树有多个根,其实是可以优化的。肯定存在一个子节点。通过这个该子节点访问到所有的节点。那么,优化后,这个子节点就成为了新的树的根节点 此外从vue 的角度来说,如果一个组件有多个根,说明你可以把这个组件拆开成两个组件,这样既进行了解耦,也会为后续的维护和迭代提供方便 |
Technical, due to how the diff algorithm is written. It's obviously possible to update it, but it takes significant changes to the current algorithm (React did that during a complete rewrite). |
组件的 |
有个问题,Vue多页面配置,怎么解释 |
呦大佬来了 |
在单文件组件和字符串模板中组件名应该总是 PascalCase 的 但是在 DOM 模板中总是 kebab-case 的。 PascalCase 相比 kebab-case 有一些优势: 编辑器可以在模板里自动补全组件名,因为 PascalCase 同样适用于 JavaScript。 视觉上比 更能够和单个单词的 HTML 元素区别开来,PascalCase 确保了你的 Vue 组件在视觉上是易识别的。 不幸的是,由于 HTML 是大小写不敏感的,在 DOM 模板中必须仍使用 kebab-case。 还请注意,如果你已经是 kebab-case 的重度用户,那么与 HTML 保持一致的命名约定且在多个项目中保持相同的大小写规则就可能比上述优势更为重要了。在这些情况下,在所有的地方都使用 kebab-case 同样是可以接受的。 |
一个组件对应一个虚拟Dom |
Vue 要求组件模板只能有一个根元素的原因是为了确保组件的渲染结果是一个单一的根节点。这样可以简化 Vue 的模板编译和虚拟 DOM 的处理逻辑,使其更加高效和可靠。 以下是一些原因解释为什么要求组件模板只能有一个根元素: 渲染性能:Vue 使用虚拟 DOM 来跟踪组件的状态和变化,并根据数据的变化来更新视图。通过要求只有一个根元素,Vue 可以更方便地创建和更新虚拟 DOM 树,从而提高渲染性能。 渲染一致性:将组件模板限制为一个根元素可以确保组件的渲染结果始终是单一的根节点。这使得在组件嵌套和组合时,样式和布局更加一致和可预测。 组件实例化和管理:在 Vue 中,组件实例是由组件模板创建的。每个组件实例都有一个根元素作为其包裹容器,它是组件实例的顶级元素。通过要求只有一个根元素,Vue 可以更好地管理组件实例的生命周期和作用域。 模板编译:Vue 的模板编译器会将模板解析为渲染函数,以生成虚拟 DOM。通过要求只有一个根元素,模板编译器可以更容易地生成有效的渲染函数代码,并处理模板中的指令、组件和表达式。 尽管组件模板只能有一个根元素,但可以使用容器元素(例如 、)来包裹多个元素,以满足布局和样式的需求。也可以使用 Vue 的 Fragments 特性(Vue 2.6+)或 Vue 3 中的 标签来实现多个根节点的效果。
总而言之,要求组件模板只能有一个根元素是为了提高渲染性能、保持渲染一致性、更好地管理组件实例和简化模板编译过程。这是 Vue 框架设计的一部分,旨在提供高效、可靠和一致的组件开发体验。 |
[vue] vue为什么要求组件模板只能有一个根元素?
The text was updated successfully, but these errors were encountered: