模块化和抽象反应组件功能 [英] Modularize and abstract react component functionality

查看:119
本文介绍了模块化和抽象反应组件功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面有一个允许复选框全部和复选框的工作组件。它完美的作品。但是我讨厌这个想法,即每次我想要使用这个特性时,都会被困在所有这些代码中。我正在寻找一种反应方式来实现这种模块化?这是

它并没有在一个地方模块化输入全部检查功能的全部功能。我必须在每次使用时移动getInitialState变量和changeHandlers。



我认为,如果输入复选框全部功能在HTML中是原生的,我们将如何使用它?我们只需要为元素提供属性,并且它们会互相引用,并且所有处理程序都会在引擎盖下发生,使用起来会很简单。这个例子的目标是让HTML级别简单。我上面展示的代码没有实现,因为它被绑定到函数处理程序和状态初始值设定项。反应是否提供了一种抽象的方式?



以下是我对这个组件所需的API。



这是一个实际的例子。



主要问题是:


  • 组件功能对父项无关紧要,这意味着父项不需要为处理程序和状态。

  • 代码当前手动跟踪每个复选框的状态,这意味着无法动态地查找DOM中有多少复选框,而无需声明它。

  • 整体模块化和易用性。



以下是代码:

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

$ b $)

var Test = React.createClass({
getInitialState:function(){
return {
检查:[false,false,false]
}
},
selectAll:function(event){
//设置所有检查状态为真
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({
$ check:checked
})
},
render:function(){
var isAllChecked = this.state.checked.filter(function(c){
返回c
))。length === this.state.checked.length

return(
< div>
全选:
< InputCheckbox onChange = {this.selectAll} checked = {isAllChecked} />
< br />
< I nCheckCheckbox 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>

$ b $)

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>

}
})
pre

解决方案

下面的例子是在我认为的正确的大方向上,一般的想法是引入一个相关的包装器组件

  var CheckAll = React.createClass({
render(){
return< input type =复选框{... 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);
},
richChild(child){
var boxes = this.props.boxes;
var all = Object.keys(boxes)。每个(k =>盒子[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;
返回React.cloneElement(child,{checked:!! boxes [name],
onChange:({target})=> this.setOne(name,target.checked)
});
} else {
return child;
}
},
render(){
re转(
< 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/>
<复选框名称=b/>
<复选框名称= c/>
< / CheckboxGroup>
< / div>

}
})

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

这里有一个jsbin - https://jsbin.com/zomuxolevo/1/edit?js,output



为了让孩子们拥有更多的灵活性,你需要递归地进行学习lk他们使用像这样的要点 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);
})
}
})


I have below a working component that allows for a checkbox all and checkboxes. It works perfectly. However I hate the idea that I'm stuck carrying all of this code around every time I want to use this feature. I'm looking for a way within react to make this modular? Is this

It doesn't modularize the entire functionality of the "input checked all" functionality in one place. I have to move the getInitialState variables and changeHandlers with each usage.

I think of it like if the "input checkbox all" functionally was native within HTML, how would we use it? We would need only supply the attributes to the elements and they would reference each other and all of the handlers would occur under the hood, it would be simple to use. My goal with this example is to have HTML level simplicity. The code I show above doesn't achieve that because it's tied down to function handlers and state initializers. Does react provide a way of abstracting this?

Below is my desired API for this component.

Here's the working example.

The main problems are:

  • The component functionality is indifferent to the parent, meaning the paren't doesn't need to store the information for the handlers and state.
  • The code currently manually tracks state for each checkbox, meaning there's no way to dynamically find how many of an a checkbox is in the DOM without stating it.
  • Overall modularity and ease-of use.

Here's the code:

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)

Ideally I can just use it like this:

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>
    )
  }
})

解决方案

The following example is in the right general direction I think, the general idea is to introduce a wrapper component for the related boxes, and then walk through the children in that component to tie them together.

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)

Here's a jsbin - https://jsbin.com/zomuxolevo/1/edit?js,output

To allow for more flexibility with the children, you'd need to recursively walk them using something like this gist 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);
    })
  }
})

这篇关于模块化和抽象反应组件功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆