我正在玩vue.js并做出反应,而我正在尝试从一本关于React的书中调整一个简单的可编辑HTML表格示例,以便学习Vue。
以下是代码中发生的事情:
我遇到的问题是第7步。我可以点击表格中的多个单元格,所有单元格中仍然会设置contenteditable =“true”。如果您查看Chrome开发工具,您会看到该可信标签粘贴到所有单击的单元格上。
我认为问题正在发生,因为我有嵌套的for循环,但我不确定如何正确地添加密钥以使其工作。我试图添加密钥,但我认为我没有正确地做到这一点。
的jsfiddle: https://jsfiddle.net/o69yaq7L/
以下是代码:
"use strict";
var headers = [
"Book", "Author", "Language", "Published", "Sales"
];
var data = [
["The Lord of the Rings", "J. R. R. Tolkien", "English", "1954-1955", "150 million"],
["Le Petit Prince (The Little Prince)", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
["Harry Potter and the Philosopher's Stone", "J. K. Rowling", "English", "1997", "107 million"],
["And Then There Were None", "Agatha Christie", "English", "1939", "100 million"],
["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1754-1791", "100 million"],
["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"],
["She: A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million"],
];
var Excel = new Vue({
el: '#app',
data: {
colData: data,
headers: headers,
colSel: -1,
rowSel: -1
},
methods: {
dataClick: function(ev){
this.colSel = ev.target.cellIndex;
this.rowSel = ev.target.parentElement.rowIndex - 1;
Vue.nextTick( function(){
ev.target.focus();
});
},
lostFocus: function(ev){
console.log(ev.target.textContent);
//var changedRow = this.colData.slice(this.rowSel,this.rowSel+1);
this.colSel = -1;
this.rowSel = -1;
console.log(this.colSel + " " + this.rowSel);
}
}
});
<html>
<head>
<title>
VUEJS Testing
</title>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th v-for="item in headers" :key="item.id">{{item}}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row,rowInd) in colData" :key="row.id">
<template v-for="(item,colInd) in row" >
<template v-if="rowInd == rowSel && colInd == colSel">
<td contenteditable="true" v-on:focusout="lostFocus" :key="item.id">{{item}}</td>
</template>
<template v-else>
<td v-on:dblclick="dataClick">{{item}}</td>
</template>
</template>
</tr>
</tbody>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.min.js"></script>
</body>
</html>
EDIT ***
问题在于代码的这一部分:
<tr v-for="(row,rowInd) in colData" :key="row.id">
<template v-for="(item,colInd) in row">
<template v-if="rowInd == rowSel && colInd == colSel">
<td contenteditable="true" v-on:focusout="lostFocus" :key="item.id">{{item}}</td>
</template>
<template v-else>
<td v-on:dblclick="dataClick">{{item}}</td>
</template>
</template>
</tr>
有两个v-for循环和一个if-else语句。问题是if语句使td元素具有contenteditable = true属性。一旦td元素获得该属性,该属性永远不会离开,即使在进一步重新呈现之后,td仍将具有contenteditable = true集,即使if语句的该部分不再对该元素产生影响。我认为我使用id标签的方式存在问题,但我不确定如何修复它。
答案 0 :(得分:3)
你必须为if / else语句提供不同的键,如下所示:
<tr v-for="(row,rowInd) in colData" :key="row.id">
<template v-for="(item,colInd) in row" >
<template v-if="rowInd == rowSel && colInd == colSel">
<td contenteditable="true" v-on:focusout="lostFocus" :key="item.id" key="key1">{{item}}</td>
</template>
<template v-else>
<td v-on:dblclick="dataClick" key="key2">{{item}}</td>
</template>
</template>
</tr>
查看更新的fiddle。
这种情况正在发生,因为Vue尝试尽可能高效地渲染元素,通常重新使用它们而不是从头开始渲染。因为在你的情况下,if和else templace使用相同的元素,不会被替换,只是它的click事件。虽然这并不总是令人满意,因此Vue提供了一种方式,您可以通过添加key
属性和唯一值来完成These two elements are completely separate - don’t re-use them。