首页 > 解决方案 > 我正在尝试实现一种删除可交换项目的方法,但是我的删除方法会删除所有项目,而不仅仅是单击的项目

问题描述

我有两个组件,App.js 包含我的“小部件”布局和 SwappableComponent.js,它创建每个可交换的小部件。我正在尝试实现删除功能,但是当我单击删除按钮时,会发生什么情况是它删除了所有可交换组件,而不仅仅是单击的那个。任何帮助,将不胜感激。

import React, { Component } from 'react';
import Swappable from './components/SwappableComponent'
import './App.css';
import DataTable from './components/tableWidget';
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";


const styles = theme => ({
  root: {
    flexGrow: 1
  },
  paper: {
    padding: theme.spacing.unit * 2,
    textAlign: "center",
    color: theme.palette.text.secondary
  }
});

class App extends Component {
    constructor(props) {
      super(props);
      this.state={
        widgets:[
          {id:1, content: <DataTable/>},
          {id:2, content: "#2"},
          {id:3, content: "#3"},
          {id:4, content: "#4"}
        ]
      }

    }  
    deleteEvent=(index)=>{
        const copyWidgets=Object.assign([],this.state.widgets);
        copyWidgets.splice(index);
        this.setState({
            widgets:copyWidgets
        })
    }
    render() {
      const { classes } = this.props;

      return (
      <div className={classes.root}>
        <Grid container spacing={24}>
            {
                this.state.widgets.map((widget,index)=>{
                    return(
                        <Grid item xs={12} sm={6}>
                            <Paper className={classes.paper}><Swappable id={widget.id} content={widget.content} delete={this.deleteEvent.bind(this,index)}/></Paper>
                         </Grid>
                    )
                })
            }
        </Grid>
      </div>
      );
    }
  }

  App.propTypes = {
    classes: PropTypes.object.isRequired
  };

  export default withStyles(styles)(App);
import React, { Component } from 'react'

class Swappable extends Component {
    constructor() {
        super()

        this.state = {
            customFunc: null
        }
    }

    allowDrop(ev) {
        ev.preventDefault();
    }

    drag(ev, customFunc = null) {
        ev.dataTransfer.setData("src", ev.target.id);
        console.log(ev.target.parentNode, 'TARGET DRAGSTART')

        this.setState({
            initialParentNode: ev.target.parentNode
        })
    }

    dragEnd(ev, customFunc = null) {

        console.log(ev.target.parentNode, 'TARGET DRAGEND')
        if (customFunc && (ev.target.parentNode != this.state.initialParentNode)) {
            console.log('custom func')
            this.props.customFunc()
        }
    }

    drop(ev, dragableId, dropzoneId, customFunc = null, swappable = true) {
        ev.preventDefault();
        let src = document.getElementById(ev.dataTransfer.getData("src"));
        let srcParent = src.parentNode;
        let target = document.getElementById(dragableId);

        console.log(src, 'dragged element');
        console.log(srcParent, 'parent of dragged');
        console.log(target, 'element to be swapped')

        swappable ? this.swapElements(src, target, srcParent) : this.transferElement(src, dropzoneId)

    }

    swapElements(src, target, srcParent) {
        target.replaceWith(src);
        srcParent.appendChild(target);
    }

    transferElement(src, dropzoneId) {
        let dropzone = document.getElementById(dropzoneId)
        dropzone.appendChild(src);
    }

    render() {
        const dropZoneStyle = {
            width: '450px',
            minHeight: '300px',
            padding: '10px',
            border: ''
        };

        const draggableStyle = {
            width: '400px',
            height: '300px',
            padding: '10px',
            border: ''
        };

        const { id, content, swappable, customFunc } = this.props
        const dropzoneId = 'drop' + id
        const dragableId = 'drag' + id

        console.log(customFunc, 'customFunc')
        return (
            <div
                id = {dropzoneId}
                onDrop={(event) => this.drop(event, dragableId, dropzoneId, customFunc, swappable)} 
                onDragOver={(event) => this.allowDrop(event)} 
                style={dropZoneStyle}>
                <div id={ dragableId }
                    draggable="true"
                    onDragStart={(event) => this.drag(event)}
                    onDragEnd = {(event) => this.dragEnd(event, customFunc)}
                    style={draggableStyle}>

                    { content }
                    <button onClick={this.props.delete}>Delete</button>
                </div>
            </div>
        )
    }
}

export default Swappable;

标签: reactjs

解决方案


删除所有项目的原因是您没有为.splice函数指定第二个参数,即要从数组中删除的项目数或deleteCount.

来自MDN 文档

如果deleteCount省略,或者如果它的值等于或大于array.length - start(即,如果它等于或大于数组中剩余的元素个数,则从start开始),则所有元素从开始到结束的数组将被删除。

要修复它,请将您的deleteEvent函数修改为以下内容:

deleteEvent = (index) => {
  const copyWidgets = Object.assign([], this.state.widgets);
  copyWidgets.splice(index, 1); // delete one item only
  this.setState({
    widgets: copyWidgets
  });
};


一个显示不同行为的简单示例:

console.log('without using second argument with splice');
const letters = ['a', 'b', 'c'];
console.log('before', letters);
letters.splice(0);
console.log('after', letters);

console.log('using second argument with splice');
const numbers = [1, 2, 3];
console.log('before', numbers);
numbers.splice(1, 1);
console.log('after splice', numbers);


推荐阅读