Vue 组件在“手动"多次使用时不会呈现......但在循环重复时有效 [英] Vue components are not rendered when used multiple times 'manually'... but works when repeated with the loop

查看:18
本文介绍了Vue 组件在“手动"多次使用时不会呈现......但在循环重复时有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个如下所示的代码.前 5 个组件被正确渲染,但接下来的 3 个组件没有正确渲染.仅呈现这 3 个中的第一个:

const test = {数据() {返回 {计数:0};},道具: {文本: {类型:数字,要求:真实}},模板:`<按钮@click="count++">[ {{text}} ] 你点击了我 {{ count }} 次.`};const app = Vue.createApp({});app.component("测试", 测试);app.mount("#app");

<身体><div id="应用程序"><div v-for="i in 5"><test :text="i"/>

<小时/><test :text="99"/><test :text="42"/><test :text="55"/>

<脚本id="vue"src="https://unpkg.com/vue@3.0.11/dist/vue.global.prod.js"></脚本></html>

显然...我希望能够不仅在循环中使用组件.我错过了什么?

顺便说一句,我能够使用最新的 vue 2.x 重现同样的行为(vue 应用程序初始化代码略有不同,ofc)

解决方案

问题是由自闭合元素引起的.请参阅下面的更新演示...

为什么

在 HTML5 规范中,仅允许在void"上使用自关闭标签.元素(空元素是那些可能永远不包含任何内容的元素 - 如 brimg 等) - 请参阅此 SO 问题 - (非空)自闭合标签在 HTML5 中是否有效?

所以这里发生的事情是浏览器会解释您无效的 HTML(加载页面时 - 甚至在 Vue 启动之前),就像这样(只需运行您的代码段,注释掉 app.mount() 并检查开发工具中的 HTML):

 

<div v-for=i in 5"><test :text="i"></test>

<小时><test :text="99"><test :text="42"><test :text="55"></测试></测试></测试>

现在很容易理解为什么 v-for 工作正常,第一个组件渲染正常,但其余的不是(test 组件没有默认插槽)

请注意,这仅在使用 in-DOM 模板时出现问题,并且在字符串模板(template 选项)或 SFC 文件(和自闭合标签实际上是 Vue ESLint 规则和 Vue 风格指南)

const test = {数据() {返回 {计数:0};},道具: {文本: {类型:数字,要求:真实}},模板:`<button @click="count++">[ {{text}} ] 你点击了我 {{ count }} 次.`};const app = Vue.createApp({});app.component("测试", 测试);app.mount("#app");

<身体><div id="应用程序"><div v-for="i in 5"><test :text="i"></test>

<小时/><test :text="99" ></test><test :text="42" ></test><test :text="55" ></test>

<脚本id="vue"src="https://unpkg.com/vue@3.0.11/dist/vue.global.prod.js"></脚本></html>

I have a code like below. 5 first componets are rendered correctly, but next 3 are not. Only first one from those 3 is rendered:

const test = {
  data() {
    return {
      count: 0
    };
  },
  props: {
    text: {
      type: Number,
      required: true
    }
  },
  template: `
    <button @click="count++">
      [ {{text}} ] You clicked me {{ count }} times.
    </button>
    `
};

const app = Vue.createApp({});
app.component("test", test);
app.mount("#app");

<!DOCTYPE html>
<html>
  <body>
    <div id="app">
      <div v-for="i in 5">
        <test :text="i" />
      </div>

      <hr />

      <test :text="99" />
      <test :text="42" />
      <test :text="55" />
    </div>

    <script
      id="vue"
      src="https://unpkg.com/vue@3.0.11/dist/vue.global.prod.js"
    ></script>
  </body>
</html>

Obviously... I want to be able to use components not only in the loops. What I missed?

BTW, this same behavior I was able to reproduce with latest vue 2.x (with slightly different vue app initialization code, ofc)

解决方案

The problem is caused by self-closing elements. See updated demo below...

Why

In HTML5 spec, self closing tags are allowed only on "void" elements (Void elements are those that may not ever contain any content - as br, img etc.) - see this SO question - Are (non-void) self-closing tags valid in HTML5?

So what happens here is that your not valid HTML is interpreted by the browser (when the page is loaded - even before Vue is started) like this (just run your snippet, comment out app.mount() and inspect the HTML in the Dev Tools):

    <div id="app">
      <div v-for="i in 5">
        <test :text="i"></test>
      </div>

      <hr>

      <test :text="99">
        <test :text="42">
          <test :text="55">
          </test>
        </test>
      </test>
    </div>

Now it is easy to see why v-for works ok, 1st component is rendered ok but the rest is not (test component has no default slot)

Note this is problem only when using in-DOM templates and works fine with string templates (template option) or SFC files (and self-closing tags are actually recommended by Vue ESLint rules and Vue style guide)

const test = {
  data() {
    return {
      count: 0
    };
  },
  props: {
    text: {
      type: Number,
      required: true
    }
  },
  template: `
    <button @click="count++">
      [ {{text}} ] You clicked me {{ count }} times.
    </button>
    `
};

const app = Vue.createApp({});
app.component("test", test);
app.mount("#app");

<!DOCTYPE html>
<html>
  <body>
    <div id="app">
      <div v-for="i in 5">
        <test :text="i"></test>
      </div>

      <hr />

      <test :text="99" ></test>
      <test :text="42" ></test>
      <test :text="55" ></test>
    </div>

    <script
      id="vue"
      src="https://unpkg.com/vue@3.0.11/dist/vue.global.prod.js"
    ></script>
  </body>
</html>

这篇关于Vue 组件在“手动"多次使用时不会呈现......但在循环重复时有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆