首页 > 解决方案 > 开发者工具中的 Vue 数组更新但不会重新渲染

问题描述

我有一个带有嵌套组件的相当复杂的对象。它看起来有点像这样(为了便于阅读而删除):

<script type="text/x-template" id="fieldset-template">
    <div class="fieldset">
        <div class="fieldset-repetition" v-for="(repetition, key) in repetitions">
            <div class="field-list">
                <field v-for="field in fields" v-bind:key="field.key" v-bind:fieldset="field.fieldset" v-bind:fieldset-key="key" v-bind:field-data="field"></field>
            </div>
            <div class="repetition-meta">
                <a class="move-repetition" v-on:click="moveUp(key)">Up</a>
            </div>
        </div>
    </div>
</script>

<script type="text/x-template" id="field-template">
    <div class="field">
        <div class="form-group">
            <label class="control-label" v-html="name"></label>
            <div class="field-repetition" v-for="(repetition, key) in repetitions">
                <div class="field-text">
                    <input class="form-control" v-model="values[key]" />
                </div>
            </div>
        </div>
    </div>
</script>



<script>
    Vue.component('set', {
        components: {
            field: {
                created: function() {
                    // populate with data
                    this.populateData();
                },
                data: function() {
                    return {
                        repetitions: [],
                        values: [],
                    }
                },
                methods: {
                    populateData: function() {
                        this.repetitions = this.fieldData.repetitions;

                        this.repetitions.forEach(function(repetition, key) {
                            this.values = this.fieldData.value[this.fieldsetKey];
                        }.bind(this));
                    },
                    repeatField: function() {
                        var field = Object.clone(this);
                        delete field.repetitions;
                        this.repetitions.push(field);
                        if (this.widget != 'checkbox') {
                            this.values.push(this.fieldData.default);
                        }
                        else {
                            this.values.push([this.fieldData.default]);
                        }
                    },
                },
                props: {
                    fieldData: {
                        type: Object
                    },
                    fieldset: {
                        type: Object
                    },
                    fieldsetKey: {
                        type: Number
                    }
                },
                template: '#field-template'
            }
        },
        data: function() {
            return {
                fields: [FieldObject1, FieldObject2, FieldObject3],
                repetitions: [RepetitionObject1, RepetitionObject2,  RepetitionObject3,  RepetitionObject4,  RepetitionObject5],
            }
        },
        methods: {
            moveUp: function(key) {
                var field = this.fields[0];
                var value = field.value[key];
                field.value[key] = field.value[key - 1];
                field.value[key - 1] = value;
                this.$set(this.fields, 0, field);
            }
        },
        template: '#fieldset-template'
    });
</script>

每当 moveUp 方法运行时,它都会更新字段对象,但字段组件不会重新呈现。

我怀疑这是因为重复的次要(外部)循环,但我想不出办法。

标签: javascriptvue.jsvuejs2vue-component

解决方案


this.$set(this.fields, 0, field);不会做任何this.fields[0]已经等于 的事情field

假设field.value是一个数组,正是这一步进行了非反应性更改:

field.value[key] = field.value[key - 1];
field.value[key - 1] = value;

https://vuejs.org/v2/guide/list.html#Caveats

你可以把它写成:

this.$set(field.value, key, field.value[key - 1]);
this.$set(field.value, key - 1, value);

或使用splice

field.value.splice(key - 1, 2, field.value[key], field.value[key - 1]);

推荐阅读