- 首页
- 前端开发
- Vue 组件在“手动"多次使用时不会呈现......但在循环重复时有效
Vue 组件在“手动"多次使用时不会呈现......但在循环重复时有效
[英] Vue components are not rendered when used multiple times 'manually'... but works when repeated with the loop
本文介绍了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"上使用自关闭标签.元素(空元素是那些可能永远不包含任何内容的元素 - 如 br
、img
等) - 请参阅此 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屋!