Vue обновлений массива в инструментах разработчика, но не рендеринг - PullRequest
4 голосов
/ 09 января 2020

У меня довольно сложный объект с вложенными компонентами. Это выглядит примерно так (урезано для облегчения чтения):

<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 он обновляет объект fields, но компонент поля не выполняет повторную визуализацию.

У меня есть подозрение, что это из-за вторичного (внешнего) цикла для повторений, но я не мог обойти это.

1 Ответ

3 голосов
/ 09 января 2020

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]);
...