【问题标题】:React input checkbox select all component反应输入复选框选择所有组件
【发布时间】:2015-12-14 23:37:47
【问题描述】:

我正在尝试构建一个正确的反应输入复选框选择所有组件。这个想法是有一个组件<InputCheckboxAll><InputCheckbox>,我可以检查<InputCheckboxAll>,并且所有<InputCheckbox> 也会被选中。

我有两个问题。

  • 如果选中<InputCheckboxAll>,我无法取消选择任何<InputCheckbox>
  • 如果检查了所有<InputCheckbox>,则应检查<InputCheckboxAll>

Here's the example.

var InputCheckboxAll = React.createClass({
  handleChange: function (event) {
    this.props.handleChange(event)
  },
  render: function () {
    return (
    <input
           type='checkbox'
           {...this.props}
           onChange={this.handleChange} />
    )
  }
})

var InputCheckbox = React.createClass({
  getInitialState: function () {
    return {
      checked: this.props.checked
    }
  },
  render: function () {
    var checkedValue = this.props.allChecked ? true : this.state.checked
    return (
    <input
           checked={checkedValue}
           type='checkbox'
           {...this.props}/>
    )
  }
})

var Test = React.createClass({
  getInitialState: function () { return {allChecked: false}; },
  handleChange: function (event) {
    var $elm = $(event.target)
    var checked = $elm.prop('checked')
    this.setState({
      allChecked: checked
    })
  },
  render: function () {
    return (
    <div>
      Select All: <InputCheckboxAll handleChange={this.handleChange}/><br/>
      <InputCheckbox allChecked={this.state.allChecked}/><br/>
      <InputCheckbox allChecked={this.state.allChecked}/><br/>
      <InputCheckbox allChecked={this.state.allChecked}/><br/>
    </div>
    )
  }
})

React.render(<Test/>, document.body)

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    我认为可以对您的实现进行一些修改,以便以更 React'esque 的形式实现所需的结果。

    您应该首先摆脱的是 InputCheckboxAll 复选框类和 InputCheckbox 类的 allChecked 属性。复选框是一个比较笨的元素,它不应该知道Everything is selected之类的概念。

    相反,复选框应该被实现为简单地选中未选中的项目。

    var InputCheckbox = React.createClass({
      getDefaultProps: function () {
        return {
          checked: false
        }
      },
      render: function () {
        return (
        <input
               checked={this.props.checked}
               type='checkbox'
               {...this.props}/>
        )
      }
    })
    

    您的应用程序的状态(诸如All Selected 之类的概念)应从主应用程序管理,保持较低级别的元素无状态。主应用程序的状态可以简单地表示每个复选框的已选中状态:

      getInitialState: function () { 
          return {
            // 3 checkboxes, all initialized as unchecked
            checked: [false, false, false]
          }; 
      },
    

    现在,您可以重新创建渲染函数来绘制 3 个复选框,以及您的全选复选框。每个&lt;InputCheckbox&gt; 都可以绑定到this.state.checked 数组中自己的数据。当&lt;Inputcheckbox&gt; 发生变化时,我们将索引绑定到更改处理程序,因此我们知道要修改哪个数组元素。

      render: function () {
        // Recalculate if everything is checked each render, instead of storing it
        var isAllChecked = this.state.checked.filter(function(c) {
            return c;
        }).length === this.state.checked.length;
    
        return (
        <div>
          Select All: <InputCheckbox 
                   onChange={this.selectAll} 
                   checked={isAllChecked}/><br/>
    
          <InputCheckbox 
                   checked={this.state.checked[0]} 
                   onChange={this.handleChange.bind(this, 0)}/><br/>
          <InputCheckbox 
                   checked={this.state.checked[1]} 
                   onChange={this.handleChange.bind(this, 1)}/><br/>
          <InputCheckbox 
                   checked={this.state.checked[2]} 
                   onChange={this.handleChange.bind(this, 2)}/><br/>
        </div>
        )
      }
    

    您不需要存储任何与All Selected 相关的状态。相反,最好在每次渲染期间重新计算是否选择了所有内容。当Select All复选框被选中时,我们只需将this.state.checked的每个元素都设置为true。

    这还有一个好处是当你手动选择所有复选框时,全选复选框会自动检查。

    这是一个示例实现: https://jsfiddle.net/rsupvxry/

    【讨论】:

    • 这真的很有帮助!非常感谢你把这个放在一起。正如你所写的那样,我对此有一个担忧。我想让这个checkbox 更加模块化,所以我可以在许多不同的项目中使用它。我不想每次都携带这些事件处理程序。我可以使用 mixin,但 apparently they're dead,而 isAllChecked var 会妨碍我。还必须为每个榆树定义状态看起来是多余的。您将如何将其进一步移植到即插即用模块化?
    • 或者 React 根本不允许这样做?
    • 您希望将哪种类型的功能模块化?您想要一组复选框,并附带一个 select all 复选框吗?或者你想要一个 SelectAllCheckbox 来包裹其他基本的复选框?这样,您就可以处理该元素中的全选逻辑。
    • 我不确定确切的区别,我假设是后者。我想要我们在这里拥有的确切功能,我不希望元素相互嵌套。我也想把这里创建的所有功能都放在某个地方,以便于使用。
    • React.13.Common/FormInputs 下github.com/calitek/ReactPatterns 有一个模块化组件用于输入。
    【解决方案2】:

    我很晚才看到这个帖子。以下解决方案适用于以下结构。

    有 3 个组件使此功能干净且可重用。

    1. CheckBox - 可重用组件
    2. CheckBoxList - 可重用组件
    3. CityList - 最终级别,您可以在其中通过克隆创建州列表或任何列表。

    Stack Blitz with Module - https://stackblitz.com/edit/react-check-box-list

    独立代码如下

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <title>React: Select All or DeSelect All</title>
            <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
            <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
            <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
            <script type="text/babel">
                function CheckBox({name, value, tick, onCheck}) {
                    return (
                        <label>
                            <input
                                name={name}
                                type="checkbox"
                                value={value}
                                checked={tick || false}
                                onChange={onCheck}
                            />
                            {value}
                        </label>
                    );
                }
    
                function CheckBoxList ({options, isCheckedAll, onCheck}) {
                    const checkBoxOptions = (
                        <div className="checkbox-list">
                            {options.map((option, index) => {
                                return (
                                    <CheckBox key={index} name={option.name} value={option.value} tick={option.checked} onCheck={(e) => onCheck(option.value, e.target.checked)} />
                                );
                            })}
                        </div>
                    );
    
                    return (
                        <div className="checkbox-list">
                            <CheckBox name="select-all" value="ALL" tick={isCheckedAll} onCheck={(e) => onCheck('all', e.target.checked)} />
                            {checkBoxOptions}
                        </div>
                    );
                }
    
                class CityList extends React.Component {
                    constructor(props) {
                        super(props);
    
                        this.state = {
                            isAllSelected: false,
                            checkList: [
                                {
                                    name: "city",
                                    value: "bangalore",
                                    checked: false,
                                },
                                {
                                    name: "city",
                                    value: "chennai",
                                    checked: false,
                                },
                                {
                                    name: "city",
                                    value: "delhi",
                                    checked: false,
                                }
                            ]
                        };
                    }
    
                    onCheckBoxChange(checkName, isChecked) {
                        let isAllChecked = (checkName === 'all' && isChecked);
                        let isAllUnChecked = (checkName === 'all' && !isChecked);
                        const checked = isChecked;
    
                        const checkList = this.state.checkList.map((city, index) => {
                            if(isAllChecked || city.value === checkName) {
                                return Object.assign({}, city, {
                                    checked,
                                });
                            } else if (isAllUnChecked) {
                                return Object.assign({}, city, {
                                    checked: false,
                                });
                            }
    
                            return city;
                        });
    
                        let isAllSelected = (checkList.findIndex((item) => item.checked === false) === -1) || isAllChecked;
    
                        this.setState({
                            checkList,
                            isAllSelected,
                        });
    
                    }
    
                    render() {
                        return (<CheckBoxList options={this.state.checkList} isCheckedAll={this.state.isAllSelected} onCheck={this.onCheckBoxChange.bind(this)} />);
                    }
                }
    
                ReactDOM.render(
                    <CityList />,
                    document.getElementById('root')
                );
            </script>
        </head>
        <body>
            <div id="root"></div>
        </body>
    </html>

    【讨论】:

      【解决方案3】:

      有一个简单的包可以解决这个问题grouped-checkboxes

      在您的情况下,渲染函数将如下所示:

      render: function () {
        return (
          <CheckboxGroup>
            Select All: <AllCheckerCheckbox /><br/>
            <Checkbox id="option-0" onChange={this.handleChange.bind(this, 0)}/><br/>
            <Checkbox id="option-1" onChange={this.handleChange.bind(this, 1)}/><br/>
            <Checkbox id="option-2" onChange={this.handleChange.bind(this, 2)}/><br/>
          </CheckboxGroup>
        )
      }
      

      更多例子见Codesandbox example

      【讨论】:

      • 请谨慎链接到您自己在不同网站上的内容,您不想成为spammer。您应该在此处包含大部分内容,并且仅将链接用作参考。
      【解决方案4】:

      我做了以下检查所有选项:

      JS代码:

       const checkAll = (e) => {
      
        var value  = false
      
        if(e.target.checked){
          value = true;
        }
        
        Array.from(document.querySelectorAll("input[name="+name+"]"))
             .forEach((checkbox) => {
              document.getElementById(checkbox.id).checked = value;
             });
       }
      

      HTML 代码(全选):

       <input type="checkbox" name="all" onChange={checkAll} />
      

      HTML 代码(选项):

       <input type="checkbox" name={name} id={name+index} value={obj.id} />
      

      选项是使用循环创建的,其中 id 对于此类复选框是唯一的。

      【讨论】:

      • 对不起,如果我问了一个愚蠢的问题,它是用于反应框架的吗?对我来说,它看起来不像反应组件。
      • @JasonLiu 是的,它是 React,我在 Hook 函数中创建了它,其中 checkAll() 是一个可以在单击检查所有输入时调用的函数。
      猜你喜欢
      • 2021-01-11
      • 1970-01-01
      • 2020-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-04
      • 1970-01-01
      相关资源
      最近更新 更多