html - 为什么这个简单的 VueJS 组件模板渲染在 DOM 中不正确的位置,在表格上方?
问题描述
下面提供的示例不是实际有问题的代码,而是尽可能接近简化的案例,以便在此处进行讨论。
破碎的例子
以下代码呈现一个表格,但意外地将组件值放在表格元素上方,无论是在视觉上还是在我在 DOM 中检查它时:
<html>
<head><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head>
<body>
<div id="app">
<table border="1">
<tr><td>A</td><td>B</td></tr>
<test></test>
<tr><td>Y</td><td>Z</td></tr>
</table>
</div>
<script>
const Test = {
template: '<tr><td>ONE</td><td>TWO</td></tr>'
}
const app = new Vue({
el: '#app',
components: { Test },
});
</script>
</body>
</html>
渲染输出:
检查的DOM:
一个类似的例子,但有效
但是,VueJS 似乎对其他嵌套对象没有问题。以下工作正常。这是同样的事情,但有一个列表:
<html>
<head><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head>
<body>
<div id="app">
<ul>
<li>TOP</li>
<test></test>
<li>BOTTOM</li>
</ul>
</div>
<script>
const Test = {
template: '<li>MIDDLE</li>'
}
const app = new Vue({
el: '#app',
components: { Test },
});
</script>
</body>
</html>
在高层次上,它们在结构上似乎是相同的——一个包含三个项目的容器。在第一种情况下,它是一个包含行(损坏)的表格,在第二种情况下,它是一个包含项目(作品)的列表。
问题
有人可以解释这种行为,引擎盖下发生了什么,理想情况下如何解决?
实际问题的背景
实际代码涉及具有表头 ( thead
) 部分和标题行 ( tr
) 的表格,而组件数据出现在表体 ( tbody
) 内部,出于各种原因,我不想用其他组件污染页面,也不更改现有组件代码。
有用的一边
虽然不相关,但对于同船的读者来说,我是偶然发现的<test/>
,<test></test>
并不是一回事。实际上,如果您使用上面的工作案例并尝试一下,您会发现最后一个元素丢失了。跳到 VueJS 并阅读关于self-close-components 的内容,因为只有官方的“void”元素可以自关闭。
解决方案
此问题与Vue.js中的DOM 模板解析有关。如文档中所述:
一些 HTML 元素,例如
<ul>
,和对可以出现在其中的元素有限制<ol>
,而一些元素例如,和只能出现在某些其他元素中。<table>
<select>
<li>
<tr>
<option>
当使用具有此类限制的元素的组件时,这将导致问题。例如:
<table> <blog-post-row></blog-post-row> </table>
自定义组件
<blog-post-row>
将作为无效内容被吊出,导致最终呈现的输出出现错误。
这与您面临的完全相同的问题,正如您的演示中<Test>
所呈现的那样。table
幸运的是,is
特殊属性提供了解决此问题的方法。您只需要<Test>
在父组件内部调用,例如:
<table border="1">
<tr><td>A</td><td>B</td></tr>
<tr is="test"></tr>
<tr><td>Y</td><td>Z</td></tr>
</table>
工作演示:
const Test = {
template: '<tr><td>ONE</td><td>TWO</td></tr>'
}
const app = new Vue({
el: '#app',
components: {
Test
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<div id="app">
<table class="table">
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr is="test"></tr>
<tr>
<td>Y</td>
<td>Z</td>
</tr>
</table>
</div>
推荐阅读
- azure - Docker containers in Azure pipelines in privileged mode possible?
- java - 媒体录音机声音质量差
- linux - 如何连接两个虚拟串口从 GPSFeed+ 读取数据?
- reactjs - useState Hook 在第一次调用该函数时不起作用
- go - 在 HTTP 请求中使用 uTLS 对象
- c++ - 如何更改 QT 中信号和插槽的时序?
- javascript - Vue.js - 如何根据状态动态绑定 v-model 到路由参数
- javascript - 我的 javascript + p5.js 代码无缘无故无法工作
- python - 总日期问题
- sql - 在 PL/SQL 中使用包含“_”符号的字符串进行 LIKE 操作