我对Vue很新,我到目前为止都喜欢它。但是,我遇到了以下问题,如果有任何建议,我会感激不尽。
我想在对象上递归迭代以获得嵌套表。
我有这个模板:
<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
,这仍然是非法的表格布局并打破它。
<script type="text/x-template">
<tbody>
<tr>
<td>...</td>
<td>...</td>
</tr>
<tr is="row-item" ...></tr>
</tbody>
</script>
小提琴:https://jsfiddle.net/rafi16d/puwcs9ay/
Vue@1.x不需要一个根元素。我该怎么办?
有没有人碰到类似的东西?
感谢。
答案 0 :(得分:1)
(可悲)Vue2迫切需要每个组件的真正根元素。 因此,我认为你没有那么多的可能性:
做两个组件而不是一个组件,并且它们都是虚拟节点:
<table>
<tbody>
<template for="row in someRows">
<tr>mainRow</tr>
<tr>subRow</tr>
</template>
</tbody>
</table>
忘掉做真正的桌子的想法。使用<div>
和related display css properties代替模拟布局。
答案 1 :(得分:1)
好吧,我设法做到了。红色边框是供您查看结构的,您可能需要调整填充。
https://jsfiddle.net/guanzo/puwcs9ay/9/
我从jQuery Datatables如何嵌套行中借用了几个hacks和想法:
您可以在td
中添加任何内容。因此,将根元素设为tr
,使用colspan 100%嵌套td
,然后可以嵌套表。由于您可以将tr
放在table
内,因此递归开始。
tr
- &gt; td
- &gt; table
- &gt; tr
- &gt; td
- &gt;无限期table
<td colspan="42">
42或任何绝对高于列数的数字基本上等于colspan="100%"
。
您也可以 - 也可能 - 使用数组的长度为colspan
提供正确的列数,我只是懒惰。
内部trs
更改了默认的css。
.inner-tr{
display: table;
width:100%;
}
答案 2 :(得分:0)
如果在计算的属性中展平树(对其进行规范化),则可以呈现HTML表而无需在组件本身内部进行递归,从而避免黑客入侵或生成无效的HTML。
public static string Capture(IWebDriver driver, string screenShotName)
{
ITakesScreenshot ts = (ITakesScreenshot)driver;
Screenshot screenshot = ts.GetScreenshot();
string pth = System.Reflection.Assembly.GetCallingAssembly().CodeBase;
string finalpth = pth.Substring(0, pth.LastIndexOf("bin")) + "ErrorScreenshots\\" + screenShotName + ".png";
string localpath = new Uri(finalpth).LocalPath;
screenshot.SaveAsFile(localpath, ScreenshotImageFormat.Png);
return localpath;
}
public void GetResult()
{
var status = NUnit.Framework.TestContext.CurrentContext.Result.Outcome.Status;
var stackTrace = "<pre>" + NUnit.Framework.TestContext.CurrentContext.Result.StackTrace + "</pre>";
var errorMessage = NUnit.Framework.TestContext.CurrentContext.Result.Message;
if (status == TestStatus.Failed)
{
string screenShotPath = Capture(DriverContext.Driver, "ScreenShotName");
Test.Log(LogStatus.Pass, stackTrace + errorMessage);
Test.Log(LogStatus.Pass, "Snapshot below: " + Test.AddScreenCaptureFromPath(screenShotPath));
}
DriverContext.Driver.Quit();
}
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;
}