首页 > 解决方案 > 数据更改时Vue.js列表不更新

问题描述

我正在尝试重新组织数据列表。我给了每个人li一个唯一的钥匙,但仍然没有运气!

我以前有过这个工作,就像下面一样,我想我快崩溃了!

let app = new Vue({
  el: '#app',
  data: {
    list: [
      { value: 'item 1', id: '43234r' },
      { value: 'item 2', id: '32rsdf' },
      { value: 'item 3', id: 'fdsfsdf' },
      { value: 'item 4', id: 'sdfg543' }
    ]
  },
  methods: {
    randomise: function() {
      let input = this.list;
     
      for (let i = input.length-1; i >=0; i--) {

          let randomIndex = Math.floor(Math.random()*(i+1)); 
          let itemAtIndex = input[randomIndex]; 

          input[randomIndex] = input[i]; 
          input[i] = itemAtIndex;
      }
      this.list = input;
     
    }
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.value }}</li>
  </ul>
  <a href="javascript:void(0)" v-on:click="randomise()">Randomize</a>
  
</div>

编辑:

感谢您的回答,老实说,我提供的示例对于我试图解决的实际问题可能不是最好的。我想我可能已经找到了问题的原因。

我基本上使用与上面类似的逻辑,除了我基于拖放移动一组对象,这适用于普通 HTML。

但是,我在其他地方使用我的拖放组件,其中包含另一个组件,这就是事情似乎分崩离析的地方......

当一个项目在它的数据中移动时,在另一个组件中拥有一个组件会阻止 Vue 重新渲染吗?

下面是我的DraggableBase组件,我扩展自:

<script>
    export default {
        data: function() {
            return {
                dragStartClass: 'drag-start',
                dragEnterClass: 'drag-enter',
                activeIndex: null
            }
        },
        methods: {

            setClass: function(dragStatus) {
                switch (dragStatus) {
                    case 0:
                        return null;
                    case 1:
                        return this.dragStartClass;
                    case 2:
                        return this.dragEnterClass;
                    case 3:
                        return this.dragStartClass + ' ' + this.dragEnterClass;
                }
            },
            onDragStart: function(event, index) {

                event.stopPropagation();

                this.activeIndex = index;
                this.data.data[index].dragCurrent = true;

                this.data.data[index].dragStatus = 3;

            },
            onDragLeave: function(event, index) {

                this.data.data[index].counter--;

                if (this.data.data[index].counter !== 0) return;

                if (this.data.data[index].dragStatus === 3) {
                    this.data.data[index].dragStatus = 1;
                    return;
                }
                this.data.data[index].dragStatus = 0;
            },
            onDragEnter: function(event, index) {

                this.data.data[index].counter++;

                if (this.data.data[index].dragCurrent) {
                    this.data.data[index].dragStatus = 3;
                    return;
                }
                this.data.data[index].dragStatus = 2;
            },
            onDragOver: function(event, index) {
                if (event.preventDefault) {
                    event.preventDefault();
                }
                event.dataTransfer.dropEffect = 'move';
                return false;
            },
            onDragEnd: function(event, index) {
                this.data.data[index].dragStatus = 0;
                this.data.data[index].dragCurrent = false;
            },
            onDrop: function(event, index) {

                if (event.stopPropagation) {
                    event.stopPropagation();
                }

                if (this.activeIndex !== index) {
                    this.data.data = this.array_move(this.data.data, this.activeIndex, index);
                }

                for (let index in this.data.data) {
                    if (!this.data.data.hasOwnProperty(index)) continue;
                    this.data.data[index].dragStatus = 0;
                    this.data.data[index].counter = 0;
                    this.data.data[index].dragCurrent = false;
                }

                return false;
            },
            array_move: function(arr, old_index, new_index) {
                if (new_index >= arr.length) {
                    let k = new_index - arr.length + 1;
                    while (k--) {
                        arr.push(undefined);
                    }
                }
                arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
                return arr; // for testing
            }
        }
    }
</script>

编辑 2

弄清楚了!以前使用循环索引效果很好,但是这次似乎不是这样!

我更改了v-bind:key使用数据库 ID,这解决了问题!

标签: vue.js

解决方案


数组有一些注意事项

由于 JavaScript 的限制,Vue 无法检测到数组的以下更改:

  • 当您直接使用索引设置项目时,例如vm.items[indexOfItem] = newValue

  • 当您修改数组的长度时,例如vm.items.length = newLength


为了克服警告 1,以下两个都将完成与 相同的操作vm.items[indexOfItem] = newValue,但也会触发反应系统中的状态更新:

Vue.set(vm.items, indexOfItem, newValue)

或者在你的情况下

randomise: function() {
      let input = this.list;
     
      for (let i = input.length-1; i >=0; i--) {

          let randomIndex = Math.floor(Math.random()*(i+1)); 
          let itemAtIndex = input[randomIndex]; 
          
          Vue.set(input, randomIndex, input[i]); 
          Vue.set(input, i, itemAtIndex);
      }
      this.list = input;
     
    }

推荐阅读