Vuejs2 - 递归迭代“tr”元素
Vuejs2 - Iterate “tr” element recursively
我是 Vue 的新手,到目前为止我很喜欢它。但是,我遇到了以下问题,对于如何解决该问题的任何建议,我将不胜感激。
我想递归迭代对象以获得嵌套的 table。
我有这个模板:
<script type="text/x-template">
<tr>
<td><a v-on:click="toggle">[+]</a></td>
<td>...</td>
</tr>
<tr is="row-item" v-show="open" ...></tr>
</script>
它是递归的,所以每一行tr
下面都有另一条隐藏线tr
。
当用户点击父行的[+]时,会出现子行。
我已经尝试将内容包装在 tbody
标签中,但后来我在 tbody
中得到了 tbody
,这仍然是一个非法的 table 布局并中断它。
<script type="text/x-template">
<tbody>
<tr>
<td>...</td>
<td>...</td>
</tr>
<tr is="row-item" ...></tr>
</tbody>
</script>
Fiddle: https://jsfiddle.net/rafi16d/puwcs9ay/
Vue@1.x 不需要一个根元素。没有我怎么办?
有没有人运行喜欢类似的东西?
谢谢。
(遗憾)Vue2 必须为每个组件提供一个真正的根元素。
所以我认为你没有那么多的可能性:
做两个组件而不是一个组件,并用一个虚拟节点迭代它们:
<table>
<tbody>
<template for="row in someRows">
<tr>mainRow</tr>
<tr>subRow</tr>
</template>
</tbody>
</table>
忘记想法做一个真正的table。使用 <div>
和 related display css properties 来模拟布局。
好的,我做到了。红色边框是给你看结构的,你可能需要调整padding。
https://jsfiddle.net/guanzo/puwcs9ay/9/
我从 jQuery Datatables 如何嵌套行中借鉴的一些技巧和想法:
您几乎可以在 td
中放入任何内容。所以让根元素成为一个tr
,嵌套一个td
,colspan 100%,然后你可以嵌套一个table。因为你可以把 tr
放在 table
里面,所以递归开始了。
tr
-> td
-> table
-> tr
-> td
-> table
无穷大
<td colspan="42">
42,或任何绝对高于您的列数的数字,基本上等同于 colspan="100%"
。
您也可以 - 并且可能应该 - 使用数组的长度来为 colspan
提供正确的列数,我只是懒惰。
内部 trs
已更改默认值 css。
.inner-tr{
display: table;
width:100%;
}
如果您在计算的 属性 中展平树(对其进行规范化),那么您可以渲染 HTML table 而无需在组件本身内递归,从而避免黑客攻击或生成无效 HTML.
Vue.component('tree-table-row', {
data() {
return {
indent: 20,
left_padding: 5
};
},
props: ['node'],
template: '#tree-table-row'
});
var app = new Vue({
el: '#tree-as-table',
data: {
tree: {
id: 0,
value: "fruits",
name: "root",
children: [
{
id: 1,
name: "A",
children: [{
id: 2,
name: "B",
value: "banana"
}],
value: "apple"
},
{
id: 3,
name: "C",
children: [{
id: 4,
name: "D",
value: "durian"
}],
value: "cherry"
}
]
}
},
computed: {
tree_array() {
return this.normalizedTree(this.tree, 0);
}
},
methods: {
normalizedTree(node, level) {
var _this = this;
var normal_element = {id: node.id, name: node.name, value: node.value, level: level};
var array_fragment = [normal_element];
if (node.children && node.children.length > 0) {
var i;
for (i=0; i < node.children.length; i++) {
array_fragment = array_fragment.concat(_this.normalizedTree(node.children[i], level+1));
};
}
return array_fragment;
}
}
});
.vue-table {
border-collapse: collapse;
font-family: sans-serif;
}
td {
border: 1px solid lightgrey;
padding: 2px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script type="text/x-template" id="tree-table-row">
<tr>
<td :style="{'padding-left': node.level * indent + left_padding + 'px'}">{{node.name}}</td>
<td>{{node.value}}</td>
</tr>
</script>
<div id="tree-as-table">
<table class="vue-table">
<tr is="tree-table-row" v-for="(node, index) in tree_array" :node="node" :key="node.id"/>
</table>
</div>
我是 Vue 的新手,到目前为止我很喜欢它。但是,我遇到了以下问题,对于如何解决该问题的任何建议,我将不胜感激。
我想递归迭代对象以获得嵌套的 table。
我有这个模板:
<script type="text/x-template">
<tr>
<td><a v-on:click="toggle">[+]</a></td>
<td>...</td>
</tr>
<tr is="row-item" v-show="open" ...></tr>
</script>
它是递归的,所以每一行tr
下面都有另一条隐藏线tr
。
当用户点击父行的[+]时,会出现子行。
我已经尝试将内容包装在 tbody
标签中,但后来我在 tbody
中得到了 tbody
,这仍然是一个非法的 table 布局并中断它。
<script type="text/x-template">
<tbody>
<tr>
<td>...</td>
<td>...</td>
</tr>
<tr is="row-item" ...></tr>
</tbody>
</script>
Fiddle: https://jsfiddle.net/rafi16d/puwcs9ay/
Vue@1.x 不需要一个根元素。没有我怎么办?
有没有人运行喜欢类似的东西?
谢谢。
(遗憾)Vue2 必须为每个组件提供一个真正的根元素。 所以我认为你没有那么多的可能性:
做两个组件而不是一个组件,并用一个虚拟节点迭代它们:
<table> <tbody> <template for="row in someRows"> <tr>mainRow</tr> <tr>subRow</tr> </template> </tbody> </table>
忘记想法做一个真正的table。使用
<div>
和 related display css properties 来模拟布局。
好的,我做到了。红色边框是给你看结构的,你可能需要调整padding。
https://jsfiddle.net/guanzo/puwcs9ay/9/
我从 jQuery Datatables 如何嵌套行中借鉴的一些技巧和想法:
您几乎可以在 td
中放入任何内容。所以让根元素成为一个tr
,嵌套一个td
,colspan 100%,然后你可以嵌套一个table。因为你可以把 tr
放在 table
里面,所以递归开始了。
tr
-> td
-> table
-> tr
-> td
-> table
无穷大
<td colspan="42">
42,或任何绝对高于您的列数的数字,基本上等同于 colspan="100%"
。
您也可以 - 并且可能应该 - 使用数组的长度来为 colspan
提供正确的列数,我只是懒惰。
内部 trs
已更改默认值 css。
.inner-tr{
display: table;
width:100%;
}
如果您在计算的 属性 中展平树(对其进行规范化),那么您可以渲染 HTML table 而无需在组件本身内递归,从而避免黑客攻击或生成无效 HTML.
Vue.component('tree-table-row', {
data() {
return {
indent: 20,
left_padding: 5
};
},
props: ['node'],
template: '#tree-table-row'
});
var app = new Vue({
el: '#tree-as-table',
data: {
tree: {
id: 0,
value: "fruits",
name: "root",
children: [
{
id: 1,
name: "A",
children: [{
id: 2,
name: "B",
value: "banana"
}],
value: "apple"
},
{
id: 3,
name: "C",
children: [{
id: 4,
name: "D",
value: "durian"
}],
value: "cherry"
}
]
}
},
computed: {
tree_array() {
return this.normalizedTree(this.tree, 0);
}
},
methods: {
normalizedTree(node, level) {
var _this = this;
var normal_element = {id: node.id, name: node.name, value: node.value, level: level};
var array_fragment = [normal_element];
if (node.children && node.children.length > 0) {
var i;
for (i=0; i < node.children.length; i++) {
array_fragment = array_fragment.concat(_this.normalizedTree(node.children[i], level+1));
};
}
return array_fragment;
}
}
});
.vue-table {
border-collapse: collapse;
font-family: sans-serif;
}
td {
border: 1px solid lightgrey;
padding: 2px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script type="text/x-template" id="tree-table-row">
<tr>
<td :style="{'padding-left': node.level * indent + left_padding + 'px'}">{{node.name}}</td>
<td>{{node.value}}</td>
</tr>
</script>
<div id="tree-as-table">
<table class="vue-table">
<tr is="tree-table-row" v-for="(node, index) in tree_array" :node="node" :key="node.id"/>
</table>
</div>