我试图用VUE实现这个目标: https://jsfiddle.net/jacekpr/roschwvL/5/
目前,我有这个: https://jsfiddle.net/jacekpr/8bhpqc5s/13/
但是当我想在risk-Component中渲染control-Component时,我仍然遇到组件中多个根元素的问题。
理想情况下,我会在风险成分的最后得到以下内容:
<control-Component v-for="control in risk.controls" :control="control" :key="risk.title + control.title" />
但是我收到了这个错误:
组件模板应该只包含一个根元素。如果您在多个元素上使用v-if,请使用v-else-if来链接它们。
知道如何解决这个问题吗?
答案 0 :(得分:0)
您可以在表格中添加多个tbody
代码。在risk-component
中换行tbody
,您可以在其中包含多个tr
。您需要进行一些重组,以便tbody
不要嵌套。
var risks = '[{"title":"Risk1", "controls":[{"title":"Control1"}, {"title":"Control2"}, {"title":"Control3"}]},' +
'{"title":"Risk2", "controls":[{"title":"Control1"}, {"title":"Control2"}, {"title":"Control3"}]},' +
'{"title":"Risk3", "controls":[{"title":"Control1"}, {"title":"Control2"}, {"title":"Control3"}]}]';
var programs = '[{"title":"Program1", "practice":"IT", "auditType":"GAT", "version":"0.01", "programId":"2017.1", "status":"draft", "risks":' + risks + '},' +
'{"title":"Program2", "practice":"IT", "auditType":"On-request", "version":"0.01", "programId":"2017.2", "status":"draft", "risks":""},' +
'{"title":"Program3", "practice":"CA", "auditType":"GAT", "version":"0.01", "programId":"2017.3", "status":"approved", "risks":' + risks + '},' +
'{"title":"Program4", "practice":"CA", "auditType":"On-request", "version":"0.01", "programId":"2018.1", "status":"draft", "risks":' + risks + '},' +
'{"title":"Program5", "practice":"OA\FA", "auditType":"GAT", "version":"0.01", "programId":"2019.1", "status":"draft", "risks":' + risks + '},' +
'{"title":"Program6", "practice":"OA\FA", "auditType":"On-request", "version":"0.01", "programId":"2020.1", "status":"approved", "risks":' + risks + '}]';
var dataO = JSON.parse(programs);
Vue.component('control-component', {
props: ['control'],
template: '<tr class="control" >' +
'<td></td>' +
'<td colspan="6"><a href="#">{{ control.title }}</a></td>' +
'</tr>'
})
Vue.component('risk-component', {
props: ['risk'],
template: '<tbody><tr class="risk" >' +
'<td></td>' +
'<td colspan="5"><a href="#">{{risk.title}}</a></td>' +
'<td><span class="signrisk"></span></td>' +
'</tr>' +
'<control-component v-for="control in risk.controls" :control="control" :key="control.title"></control-component>' +
'</tbody>'
});
var programTable = new Vue({
el: '#programTable',
data: {
programs: ''
}
})
programTable.programs = dataO;
&#13;
.signprogram:after {
content: "+";
display: inline-block;
cursor: pointer;
}
.expandprogram:after {
content: "-";
cursor: pointer;
}
.signrisk:after {
content: "+";
display: inline-block;
cursor: pointer;
}
.expandrisk:after {
content: "-";
cursor: pointer;
}
th {
background-color: #e0e0e0;
}
.program {
background-color: #e9e9e9;
}
.risk {
background-color: #eeeeee;
}
.control {
background-color: #f2f2f2;
}
.spacing {
background-color: white;
}
&#13;
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<table class="table" width="300px" id="programTable">
<thead>
<tr>
<th>Status</th>
<th>Title</th>
<th>Practice</th>
<th>Audit Type</th>
<th>Version</th>
<th>Program</th>
<th> </th>
</tr>
</thead>
<template v-for="program in programs">
<tbody>
<tr class="program" >
<td v-if="program.status == 'draft'" style="width: 20px; background-color: lightblue;"> </td>
<td v-if="program.status == 'approved'" style="width: 20px; background-color: lightgreen;"> </td>
<td><a href="/auditprograms/1">{{program.title}}</a></td>
<td>{{program.practice}}</td>
<td>{{program.auditType}}</td>
<td>{{program.version}}</td>
<td>{{program.programId}}</td>
<td><span class="signprogram"></span></td>
</tr>
</tbody>
<risk-component v-for="risk in program.risks" :risk="risk" :key="program.title + risk.title"></risk-component>
</template>
</table>
&#13;
答案 1 :(得分:0)
对于类似的问题,我打算给出另一个答案:Vue js error: Component template should contain exactly one root element
在您的情况下,您必须将<tbody/>
委派给功能组件,这样才能构造<tr/>
组件的列表。
或者将<table/>
委托给功能组件tha将构造<tbody/>
组件的列表。
或两者兼有。
在此处复制/粘贴:
如果出于任何原因,您不想添加包装器(在我的第一种情况下,该包装器用于<tr/>
组件),则可以使用功能组件。
components/MyCompo.vue
文件夹中只有几个文件,而不是一个components/MyCompo
:
components/MyCompo/index.js
components/MyCompo/File.vue
components/MyCompo/Avatar.vue
采用这种结构,您调用组件的方式不会改变。
components/MyCompo/index.js
文件内容:
import File from './File';
import Avatar from './Avatar';
const commonSort=(a,b)=>b-a;
export default {
functional: true,
name: 'MyCompo',
props: [ 'someProp', 'plopProp' ],
render(createElement, context) {
return [
createElement( File, { props: Object.assign({light: true, sort: commonSort},context.props) } ),
createElement( Avatar, { props: Object.assign({light: false, sort: commonSort},context.props) } )
];
}
};
如果两个模板中都使用了某些功能或数据,则将它们作为属性传递就可以了!
我让您想象使用此模式构建组件列表以及如此多的功能。