javascript - 使用 dragula 重新排序时如何保留对象属性?

标签 javascript reactjs dragula

以下代码用于从 API 端点获取颜色列表的简单组件。然后用户可以在左容器和右容器之间拖动颜色。在 componentDidMount 生命周期方法中,组件将 API 中的所有颜色作为具有以下属性的对象推送到组件的状态中:

{ id, name, index }

当状态更新时,这些颜色会正确地放入左侧容器中。右边的容器仍然是空的。

render 方法中,如果我添加一个记录器来吐出 availableColors 数组,每个对象都有一个名称、ID 和索引。应该如此。例如:

{ id: 1, name: 'red', index: 0 }

但是当我将颜色从左侧容器拖放到右侧容器中并执行 dragula on drop 回调时,我只能访问添加到右侧容器的每种颜色的 innerHTML。这意味着我失去了对象的属性,例如它从 API 获得的 ID。

换句话说,在我插入 newColorList 的地方,color.id 是空白的。我认为我的问题是我不应该使用以下方法获取丢弃的元素:

const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");

我应该如何修复此代码?

class DragApp extends Component {
  constructor(props) {
    super(props);

    this.state = {
      availableColors: [],
      selectedColors: []
    }
  }

  componentDidMount() {
    fetch('/api/color-list.json')
      .then(function(response) {
        return response.json()
      })
      .then(function(json) {
        var availableColors = [];

        json.forEach(function(color, index) {
          availableColors.push({ index, name: color.name, id: color.id })
        });

        this.setState({ availableColors });
      }.bind(this))
      .catch(function(ex) {
        // handle failure
      });

    dragula([document.querySelector('#left'), document.querySelector('#right')])
      .on('drop', function(el, _) {
          const newColorList = [];
          const targetContainer = document.querySelector('#right');
          const selectedColorItems = targetContainer.getElementsByTagName("li");

          Array.from(selectedColorItems).forEach(function(color) {
            // getIndexInParent returns index of element
            const index = getIndexInParent(color);
            newColorList.push({ index, name: color.innerHTML, id: color.id })
          })

          this.setState({ selectedColors: newColorList });
      }.bind(this));
  }

  render() {
    const colorsList = this.state.availableColors;
    const colors = colorsList.map((color) =>
      <li key={ color.id }>
        { color.name }
      </li>
    );

    return (
      <div className='wrapper'>
        <ul id="left" className="container">
          { colors }
        </ul>

        <ul id="right" className="container"></ul>
      </div>
    )
  }
}

最佳答案

我建议使用数据属性来存储你的颜色信息并在你放下 li 时检索它们:

class DragApp extends Component {
    constructor(props) {
        super(props);

        this.state = {
            availableColors: [],
            selectedColors: []
        }
    }

    componentDidMount() {
        fetch('/api/color-list.json')
            .then(function(response) {
                return response.json()
            })
            .then(function(json) {
                var availableColors = [];

                json.forEach(function(color, index) {
                    availableColors.push({
                        index,
                        name: color.name,
                        id: color.id
                    })
                });

                this.setState({
                    availableColors
                });
            }.bind(this))
            .catch(function(ex) {
                // handle failure
            });

        dragula([document.getElementById('#left'), document.getElementById('#right')])
            .on('drop', function(el, _) {
                const targetContainer = document.querySelector('#right');
                const selectedColorItems = targetContainer.getElementsByTagName("li");
                newColorList = Array.from(selectedColorItems).map(function(color) {
                    return {
                        index: color.dataset.index,
                        id: color.dataset.id,
                        name: color.text
                    };
                });
                this.setState({
                    selectedColors: newColorList
                });
            }.bind(this));
    }

    render() {
        const colorsList = this.state.availableColors;
        const colors = colorsList.map((color) =>
            <li key = { color.id } data-id="{ color.id }" data-index="{ color.index }">
                { color.name }
            </li>
        );

        return (
            <div className='wrapper'>
                <ul id="left" className="container">
                    { colors }
                </ul>

                <ul id="right" className="container"> </ul>
            </div>
        )
    }
}

如果你想保持getIndexInParent的想法,你应该使用array.find()

var getIndexInParent = function getIndexInParent(id) {
    return this.state.availableColors.find(function(color) {
        return color.id == id;
    });
};

关于javascript - 使用 dragula 重新排序时如何保留对象属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43918675/

相关文章:

javascript - 拖古拉已加载但不工作

javascript - 无法遍历数组比较文本值, Protractor 未定义结果

javascript - getSubscription 返回一个空订阅

reactjs - 使用 webpack 捆绑一个 React 组件以供另一个 React 组件导入

javascript - React JS 条件更新状态

Angular2/Ionic2 + ng2-dragula 有人让它工作吗?

javascript - NodeJS - LDAPJS 错误 : events. js:160 throw er;//未处理的 'error' 事件

javascript - 单击并再次单击后更改 div 内容

node.js - 如何设置 cookies express, react.js

angular - 通过angular2中的html元素获取模型