【发布时间】:2016-12-07 12:00:25
【问题描述】:
我正在使用 vue.js 和 react,我目前正在尝试从一本关于 React 的书中改编一个简单的可编辑 HTML 表格示例,以便学习 Vue。
以下是代码中发生的情况:
- 用户点击 td 元素
- td 元素的坐标存储在 rowSel、colSel 变量中
- 坐标变化导致 Vue 重新渲染视图
- 用户点击的td单元格添加了“contenteditable=true”属性,并添加了focusout事件监听器
- 然后用户可以更改 td 单元格中的数据,并单击该单元格以停止编辑(触发聚焦)
- 当用户单击单元格时,rowSel 和 colSel 变量会被重置,从而导致重新渲染
- vue 重新渲染视图,并且由于坐标被重置,Vue 应该从有问题的 td 元素中删除 contenteditable 和 focusout
- 包含表格数据的数据数组随后将使用用户在单元格可编辑时输入的文本进行更新(尚未实现)
我遇到的问题是第 7 步。我可以单击表格中的多个单元格,并且所有单元格中仍会设置 contenteditable="true"。如果你查看 Chrome 开发工具,你会看到 contenteditable 标签贴在所有被点击的单元格上。
我相信问题的发生是因为我有嵌套的 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>
编辑***
问题出在这部分代码上:
<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 标签的方式存在问题,但我不确定如何解决。
【问题讨论】:
-
请更新 sn-p 以显示必须显示的值以进行调试,因为目前它只是表格,很难说发生了什么,因为 vue-devtools 无法在 jsfiddle 上运行
标签: javascript vue.js