为什么这个简单的VueJS组件模板呈现在表格上方DOM中的不正确位置? [英] Why is this simple VueJS component template rendering in the incorrect place within the DOM, above a table?

查看:32
本文介绍了为什么这个简单的VueJS组件模板呈现在表格上方DOM中的不正确位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面提供的示例不是实际的有问题的代码,但出于在此讨论的目的,我尽可能地简化了代码.

断例

以下代码呈现了一个表,但是在视觉上和在DOM中检查它时,都将Component值意外地放在了表元素的上方 :

The following code renders a table, but puts the Component values, unexpectedly, above the table element, both visually and when I inspect it in the 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在使用其他嵌套对象时似乎没有问题.以下工作正常.这是同一件事,但有一个列表:

However, VueJS doesn't seem to have a problem doing it with other nested objects. The following works just fine. Here's the same thing, but with a list:

<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>

从高层看,它们在结构上似乎是等效的-一个包含三个项目的容器.在第一种情况下,它是一个包含行(破碎)的表,在第二种情况下,它是一个包含项(工作)的列表.

At a high level, these appear to be equivalent in structure -- one container containing three items. In the first case it's a table holding rows (broken), in the second it's a list holding items (works).

问题

有人可以解释这种行为,幕后发生的事情以及理想情况下如何解决吗?

Can someone explain the behavior, what's going on under the hood, and ideally how to fix?

实际问题的背景

实际的代码涉及到具有表头( thead )部分和标题行( tr )的表,而组件数据出现在表主体内部( tbody ),并且出于各种原因,我不想使用其他组件来污染页面,也不想更改现有的组件代码.

The actual code involves the table having a table header (thead) section with a title row (tr), while the component data appears inside of a table body (tbody), and for various reasons I do not want to pollute the page with additional components, nor alter existing component code.

有用的地方

尽管没有关联,但对于类似船上的读者,我偶然发现< test/> < test></test> 同样的事情.实际上,如果您采用上面的工作案例并进行尝试,您会发现最后一个元素丢失了.跳至VueJS并阅读有关自动关闭组件的信息,仅作为官方无效"元素可以自动关闭.

And while unrelated, for readers in a similar boat, I discovered by accident <test/> and <test></test> are not the same thing. In fact, if you take the working case above and try it, you'll discover the last element goes missing. Pop on over to VueJS and read about self-closing-components, as only official "void" elements can be self-closing.

推荐答案

此问题与

This issue is related to DOM template parsing in Vue.js. As mentioned in the docs:

一些HTML元素,例如< ul> < ol> < table> <select> 对哪些元素可以出现在其中有限制,并且某些元素(例如< li> < tr> < option> 只能出现在某些其他元素内.

Some HTML elements, such as <ul>, <ol>, <table> and <select> have restrictions on what elements can appear inside them, and some elements such as <li>, <tr>, and <option> can only appear inside certain other elements.

在将组件与具有此类限制的元素一起使用时,这将导致问题.例如:

This will lead to issues when using components with elements that have such restrictions. For example:

<table>
   <blog-post-row></blog-post-row>
</table>

自定义组件< blog-post-row> 将作为无效内容悬挂,导致最终呈现的输出中出现错误.

The custom component <blog-post-row> will be hoisted out as invalid content, causing errors in the eventual rendered output.

这是您面临的完全相同的问题,因为< Test> 在演示中的 table 外部已呈现.幸运的是, is 特殊属性提供了解决此问题的方法.您只需要在父组件内调用< Test> 即可,例如:

This is the exact same issue that you are facing, as <Test> is rendered outside the table in your demo. Fortunately, the is special attribute offers a workaround for this issue. You will simply need to call <Test> inside parent component like:

<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>

这篇关于为什么这个简单的VueJS组件模板呈现在表格上方DOM中的不正确位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆