模块化和抽象化组件功能

托马斯·里德

我在下面的工作组件中允许所有复选框和复选框。它完美地工作。但是我讨厌这样的想法:每次我想使用此功能时,我都会坚持携带所有这些代码。我正在寻找一种使之模块化的方法?这是

它并没有在一个地方模块化“输入全部检查”功能的全部功能。我必须随着每种用法移动getInitialState变量和changeHandlers。

我认为如果“输入复选框全部”功能上是HTML内建的,我们将如何使用它?我们只需要为元素提供属性,它们就可以相互引用,并且所有处理程序都将在后台进行,使用起来很简单。这个示例的目标是使HTML级别简单。我上面显示的代码无法实现,因为它与函数处理程序和状态初始化程序绑定在一起。反应是否提供了一种抽象的方法?

下面是我想要的此组件的API。

这是工作示例。

主要问题是:

  • 组件的功能与父组件无关,这意味着不需要为处理程序和状态存储信息。
  • 该代码当前手动跟踪每个复选框的状态,这意味着无法在不声明DOM的情况下动态查找DOM中有多少个复选框。
  • 整体模块化和易用性。

这是代码:

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

var Test = React.createClass({
  getInitialState: function () {
    return {
      checked: [false, false, false]
    }
  },
  selectAll: function (event) {
    // Set all checked states to true
    this.setState({
      checked: this.state.checked.map(function () {
        return event.target.checked
      })
    })
  },
  handleChange: function (index, event) {
    var checked = this.state.checked
    checked[index] = event.target.checked
    this.setState({
      checked: checked
    })
  },
  render: function () {
    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>
    )
  }
})

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

理想情况下,我可以像这样使用它:

var Checkbox = require('./Checkbox')

var Test = React.createClass({
  render: function () {
    return (
      <div>
        <Checkbox id="alpha"/>
        <Checkbox htmlFor="alpha"/>
        <Checkbox htmlFor="alpha"/>
        <Checkbox htmlFor="alpha"/>
      </div>
    )
  }
})
格兰杰明

我认为以下示例是朝正确的总体方向发展的,总体思路是为相关盒子引入包装器组件,然后遍历该组件中的子组件将它们绑在一起。

var CheckAll = React.createClass({
render() {
  return <input type="checkbox" {...this.props} />
}
});
var Checkbox = React.createClass({
render() {
  return <input type="checkbox" {...this.props} />
}
});
var CheckboxGroup = React.createClass({
setAll(to) {
  var result = {};
  Object.keys(this.props.boxes).forEach(k => result[k] = to)
  this.props.onChange(result);
},
setOne(name, to) {
  var result = {};
  Object.keys(this.props.boxes).forEach(k => result[k] = this.props.boxes[k])
  result[name] = to;
  this.props.onChange(result);
},
enrichChild(child) {
  var boxes = this.props.boxes;
  var all = Object.keys(boxes).every(k => boxes[k]);
  if (child.type == CheckAll) {
    return React.cloneElement(child, { checked: all,
      onChange: () => this.setAll(!all)
    });
  } else if (child.type == Checkbox) {
    var name = child.props.name;
    return React.cloneElement(child, { checked: !!boxes[name],
      onChange: ({target}) => this.setOne(name, target.checked)
    });
  } else {
    return child;
  }
},
render() {
  return (
    <div>
      {React.Children.map(this.props.children, this.enrichChild)}
    </div>
  )
}
});


var Test = React.createClass({
  getInitialState: function () {
    return {
      boxes: {
        a: true,
        b: false,
        c: false,
      }
    }
  },
  render: function () {
    return (
    <div>
      <CheckboxGroup
        boxes={this.state.boxes}
        onChange={boxes => this.setState({boxes})}
      >
        <CheckAll />
        <Checkbox name="a" />
        <Checkbox name="b" />
        <Checkbox name="c" />
      </CheckboxGroup>
    </div>
    )
  }
})

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

这是一个jsbin- https ://jsbin.com/zomuxolevo/1/edit ? js,输出

为了让孩子们有更大的灵活性,您需要使用类似以下要点的东西递归地走路他们:https://gist.github.com/dandelany/1ff06f4fa1f8d6f89c5e

var RecursiveChildComponent = React.createClass({
  render() {
    return <div>
      {this.recursiveCloneChildren(this.props.children)}
    </div>
  },
  recursiveCloneChildren(children) {
    return React.Children.map(children, child => {
      if(!_.isObject(child)) return child;
      var childProps = {someNew: "propToAdd"};
      childProps.children = this.recursiveCloneChildren(child.props.children);
      return React.cloneElement(child, childProps);
    })
  }
})

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章