首页 > 解决方案 > 如何从作为道具传递的数组中反应性地删除一个对象,以便它反映在 DOM 中?

问题描述

我有以下刀片文件:

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-8 col-xl-7 mx-auto">
                <items :items="{{ $items  }}" />
            </div>
        </div>
    </div>
@endsection

其中$items是从控制器中提取的 JSON 对象数组。现在,该items组件如下所示:

<template>
    <div>
        <item v-for="(item, key) in computedItems" :key="key" :item="item"/>
    </div>
</template>

computedItems属性如下所示:

computed: {
    computedItems() {
        // referring to the prop that is passed from the blade file
        let items = this.items;

        if (this.filterOptions.type !== 'Clear') {
            items = items.filter(i => i.status === this.filterOptions.type);
        }

        if (this.searchOptions.query.trim() !== '') {
            items = items.filter(
                i => i.name.toLowerCase().indexOf(this.searchOptions.query.toLowerCase()) !== -1
            );
        }

        if (this.sortOptions.type === 'asc') {
            items.sort((a, b) => a.id - b.id);
        } else if (this.sortOptions.type === 'desc') {
            items.sort((a, b) => b.id - a.id);
        }

        return items;
    }
}

item子组件中,您可以items通过如下方法删除:

methods: {
    _delete() {
        const _confirm = confirm('Are you sure you want to delete this item?');

        if (!_confirm) {
            return;
        }

        axios.delete(`/items/${this.item.id}`).then(response => {
            this.$eventBus.$emit('deleted', { id: this.item.id })
        });
    }
}

事件被父级(items组件)接收并处理:

deleted(item) {
    const i = this.items.findIndex(_i => item.id === _i.id);

    this.items.splice(i, 1);
}

但是由于某种原因,DOM 没有更新,并且v-for仍在显示已删除的对象,但是,如果我转储该道具,则表明它已被修改。我的怀疑是 Vue 无法判断该对象已被修改,因为它propsdata. 我尝试了以下方法:

现在,我知道你不能直接改变道具,因为那是反模式,所以我使用了计算道具,但我的更改仍然没有反映在 DOM 中。

那么,为什么 DOM 没有更新呢?

标签: javascriptlaravelvue.jsvuejs2

解决方案


按要求发表我的评论,我将列出该主题的要点:

  • 单向数据流:没有道具突变。如果有一个 prop 需要在组件中进行本地变异,首先将其克隆到数据并变异克隆。

  • 使用Vuex而不是事件总线进行状态/事件管理

  • Vuex 允许全局状态,可以通过操作以受控方式从组件内部(或其他地方)改变。数据从存储流下来并通过映射/调用的动作向上发出。


推荐阅读