在React中,点击按钮时添加和删除HTML元素

4

如何仅使用React而不使用jQuery或其他库来实现此jQuery fiddle的最佳简单方法是什么?我还没有掌握ReactJS技能,想知道是否有一种动态创建和删除元素的方法。

我在考虑创建一个

this.state = { "inputs": ["<input type="text" /><input type="checkbox" />"] }

状态变量数组保存添加的HTML,根据索引为每个元素分配一个唯一键,然后使用.map()方法,但我不确定是否有更简单的方法来实现这一点,也不确定如何删除每个元素。希望能得到任何帮助或反馈,谢谢!
3个回答

15

这里是一种“React”的方法来实现这个功能,我不是React专家,所以代码可能有待改进,欢迎纠正。

  • 是的,React有更多的样板代码,因为您不直接处理DOM,并且有更少的“魔法”,这意味着您总体上拥有更多的控制权(特别是作为受控组件)。
  • 状态应尽可能少,您只需要保存纯数据,而其他装饰性内容应由组件来处理。
  • 根据情况,您可以将Row组件分成两个具有更多属性的独立组件。
  • ??? 更多建议?

更新:在过去的三年里,我每天都使用React工作,我发现之前的代码存在一些不良实践,我已经更新了代码,希望它能变得更加清晰。

const Row = function(props){
  const {checked, value, onChange, onChecked} = props;
  return (
    <div>
      <input 
        type="checkbox" 
        checked={checked}
        onChange={onChecked}
        />
      <input type ="text" value={value}  onChange={onChange}/>
    </div>
  );
}

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      rows: [
        {value: 'row1', checked: false},
        {value: 'row2', checked: true},
        {value: 'row3', checked: false},
      ]
    };
  }
  
  updateValue = (e, idx) => {
    const rows = [...this.state.rows];  // copy array because we don't want to mutate the previous one
    rows[idx].value = e.target.value;
    this.setState({
        rows,
    });
  }
  
  onChecked = (idx) => {
    const rows = [...this.state.rows];  // copy array because we don't want to mutate the previous one
    rows[idx].checked = !rows[idx].checked;
    this.setState({
        rows,
    });
  } 
  
  addRow = () => {
    const rows = [...this.state.rows, 
                  {value:'', checked: false}
                 ];
    this.setState({
        rows,
    });
  }
  
  deleteRows = () => {
    this.setState({
      rows: this.state.rows.filter(e => !e.checked)
    });
  }
 
  render(){
    return(
      <div>
        {this.state.rows.map((row, idx) => {
          return(
              <Row 
                key={idx} 
                value={row.value}
                checked={row.checked}
                onChange={(e) => this.updateValue(e, idx)} 
                onChecked={() => this.onChecked(idx)}
                /> 
            )
        })
        }
        <button onClick={this.addRow}>
          add 
        </button>
        <button onClick={this.deleteRows}>
          delete
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.development.js"></script>

<div id="app"> </div>


嗨,抱歉,快速提问:在移除一个元素时,是否应该先移除与该元素相关联的所有事件?例如,我想删除第二行,是否应该先删除绑定在第二行元素上的“onChange”和“onChecked”事件,然后再移除该元素?谢谢 - JustANewCoder
1
你不需要这样做,因为这些不是由addEventListener添加的,如果DOM不再存在,浏览器会自动释放它们。还可以参考此链接以获取帮助:https://dev59.com/qGw15IYBdhLWcg3w3vle - Yichz

1

只需使用旧的普通 JS 方法

 var elem = document.getElementById("button_" + id);
 elem.parentNode.removeChild(elem);

3
我已阅读,getElementById 不推荐在 React 中使用。 - Tobi
为什么ReactJS不像其他花哨的JS库一样,你能告诉我它为什么不好吗? - Martin Tonev
请告诉我是否正确理解了这个回答:https://dev59.com/SVoT5IYBdhLWcg3w2SYT#58352254 - Tobi
好的,我使用它就像这样,没有任何问题! - Martin Tonev
在React中,您不应手动从DOM中删除/添加元素,这样做将不使用React的虚拟DOM,并且也不会使用React的优势,而且很可能会导致问题。 - Oner T.
我在许多大型项目中使用过它,没有出现任何问题。如果这不是正确的方法,请提出更好的建议! - Martin Tonev

0
在我看来,将要创建的元素存储在一个变量中。每当你想要创建一个元素时,将其推入一个数组中,然后通过数组映射渲染它,如果你想要删除,可以使用pop()来移除数组中的最后一个项目。
注意:当元素是字符串时,必须使用dangerouslySetInnerHTML来呈现它。
编程愉快!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接