vue.js不更新嵌套v-for循环中的属性

问题描述:

我正在玩vue.js并作出反应,并且我正在尝试修改一本简单的可编辑HTML表格示例为了学习Vue。vue.js不更新嵌套v-for循环中的属性

这里是代码会发生什么:

  1. 用户点击TD元素TD元素的
  2. 坐标存储在ROWSEL上,COLSEL变量
  3. 坐标变化导致Vue的重新渲染视图
  4. 用户点击的td单元格添加了“contenteditable = true”属性,并添加了聚焦事件监听器
  5. 用户可以更改td单元格中的数据,然后单击o FF细胞停止编辑(事件的内容触发)
  6. 当用户点击断电池中,ROWSEL和COLSEL变量被复位从而导致重新渲染
  7. VUE重新呈现视图,并且由于坐标被复位,Vue的应该删除CONTENTEDITABLE和有关从TD元件事件的内容
  8. 包含表数据的数据阵列将随后与文本来更新所述用户输入时,此单元为可编辑的(尚未实现)

的我遇到的问题是与第7步。我可以单击我的表中的多个单元格和所有的单元格将仍然contenteditabl e =“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({ 
 
\t el: '#app', 
 

 
\t data: { 
 
\t \t colData: data, 
 
\t \t headers: headers, \t \t 
 
\t \t colSel: -1, 
 
\t \t rowSel: -1 
 
\t }, 
 
\t methods: { 
 
\t \t dataClick: function(ev){ \t 
 
\t \t \t this.colSel = ev.target.cellIndex; 
 
\t \t \t this.rowSel = ev.target.parentElement.rowIndex - 1; 
 
\t \t \t Vue.nextTick(function(){ 
 
\t \t \t \t ev.target.focus(); 
 
\t \t \t }); 
 
\t \t }, 
 

 
\t \t lostFocus: function(ev){ \t \t \t \t \t \t 
 
\t \t \t console.log(ev.target.textContent); 
 
\t \t \t //var changedRow = this.colData.slice(this.rowSel,this.rowSel+1); 
 
\t \t \t this.colSel = -1; 
 
\t \t \t this.rowSel = -1; 
 
\t \t \t console.log(this.colSel + " " + this.rowSel); 
 
\t \t \t 
 
\t \t } 
 
\t } 
 
});
<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"> 
 
       \t <template v-for="(item,colInd) in row" > 
 
       \t \t <template v-if="rowInd == rowSel && colInd == colSel"> 
 
        \t \t <td contenteditable="true" v-on:focusout="lostFocus" :key="item.id">{{item}}</td> 
 
        \t </template> 
 
        \t <template v-else> 
 
        \t \t <td v-on:dblclick="dataClick">{{item}}</td> 
 
        \t </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标签的方式存在问题,但我不确定如何解决此问题。

+0

请更新代码显示值,它必须显示调试它作为目前它只是表和很难说什么是因为vue-devtools不工作在jsfiddle –

你必须给不同的键都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尝试尽可能高效地呈现元素,通常重新使用它们而不是从头开始呈现。既然在你的情况下,如果和其他templace使用相同的元素,不会被替换,只是它的点击事件。尽管这并不总是令人满意的,所以Vue提供了一种方法让您说,These two elements are completely separate - don’t re-use them,可以通过将key属性添加到唯一值来完成。

+0

你能告诉我什么区别“键“和”:键“(前面有冒号的键)是?我在Vue网站上看到了使用“:key”添加密钥的参考资料,例如:https://vuejs.org/v2/guide/list.html#key。 – kholdstayr

+1

':key'相当于'v-bind:key',它用来将它绑定到动态值,即i。即任何vue实例都是可变的。 – Saurabh