今天学习完 vue 组件之后做案例的时候,发现写自闭合组件的话,自闭合组件之后的标签就显示不出来了,一开始一直找不到原因,后来发现把自闭合改成正常的标签就解决问题了,于是在网上找了半天关于这个问题的解决方案,发现基本没有,接下来我就结合我做案例时遇到的问题和官方的文档说一下这个问题
首先来看一下问题
1、这个是使用自闭合标签
下面是在开发者工具中看到,只显示出来两个组件,第三个 hello 组件没有显示出来
2、这个是正常写标签组件
下面是在开发者工具中看到,三个组件都正常显示出来
3、这是将自闭合组件写在最后一个
下面是在开发者工具中看到的,如果只是最后一个组件为自闭合组件的话,也不会出现什么问题
原因分析
用户看到页面,整个渲染过程粗略说可以分为 2 步:
- 浏览器解析 HTML 标签
- 挂载 Vue 并完成渲染
出问题的地方在第一步浏览器解析 HTML 标签,所以这个问题本质上是 HTML 解析问题。
具体解释如下:
- HTML5 标准中的
Normal elements
不支持自闭合标签写法(包括自定义标签,但排除空标签和 svg 等特定标签),自闭合标签在解析时会被省略掉表示闭合的/
,即<hello/>
实际上是当成<hello>
来解析的 - 根据标准,
<hello>
就会被解析为标签的开始,这样浏览器会认为它缺少了标签结尾 -
关键的一步来了:浏览器会在父标签的结尾前,自动补全当前标签的结尾,所以自闭合标签在这样的机制下就变成了它后面兄弟节点的父节点
<!-- 原始 html --> <div class="container"> <hello /> <div class="sibling"> <p>我是示例文本</p> </div> </div> <!-- 浏览器补充后,实际 html --> <div class="container"> <hello> <div class="sibling"> <p>我是示例文本</p> </div> </hello> </div>
- 这就是为什么上面,Vue 渲染后的组件只剩下了组件模版的内容,而兄弟节点的内容消失了。因为对 Vue 来说,这个时候自闭合标签和它的兄弟节点都只是组件标记的一部分,都会被替换为组件模版
- 当自闭合标签是最后一个子节点的时候,自动补全结束标签不会影响到其他的兄弟节点,所以 Vue 渲染后就表现为一切正常,所以这就是为什么自闭合组件放在最后一个没事的原因
官方文档说明
以上就是我对自闭合标签的理解以及官方文档的一些说明,如果有什么问题可以给我指出来,大家共同进步,下面附上 vue 风格指南的官方文档,感兴趣的小伙伴可以看看