React-Native 中自定义checkbox组件

来源:互联网 发布:lol数据库魔切 编辑:程序博客网 时间:2024/06/05 14:32

这次给大家分享一下 React中 ListView这个组件以及全选和单选按钮的封装使用。当然核心部分还是讲解自定义封装的 checkbox 组件!
React 有一个优势就是组件的复用性特别高,在原生组件中,官方并没有向我们提供checkbox这样的多选或单选的组件,因此需要我们自己去封装。

https://github.com/crazycodeboy/react-native-check-box

http://www.cnblogs.com/huangjialin/p/6180200.html

checkbox组件封装

准备条件

若我们需要在列表的右侧展现checkbox那样的复选框,一般在网页中会有自带的checkbox标签元素,那在react中我们需要用图片或者字体图标来实现checkbox样式的显示,当然也可以通过样式来控制

  • 字体图标方式
    在此我们需要通过npm的方式去安装 字体图标的依赖包,传送门 点我点我

    12345678
    npm install react-native-vector-icons --save安装完毕后,我们通过require的方式,将包导入进来,如下var Icon=require('react-native-vector-icons/FontAwesome');render(){return <Icon name='square-o' size={16} style={styles.checkbox} color="#00B4F7" ></Icon>}
  • 图片方式
    这种就比较简单了,直接用原生的Image组件去加载本地的资源图片就可以了,设计好checkbox 选中和未选中两张图片,通过state去切换图片的source属性。

    12345
    var sourceUrl = require('image!selected');if(this.state.checked){  sourceUrl = require('image!unselected');}<Image source={sourceUrl}></Image>

组件核心代码

这里组件的编码,我暂时用的es6的语法,不清楚es6与es5 ,请前往此处去了解 传送门

//这里我就只贴出核心代码,关于checkbox的label属性及样式我就省略了,具体代码大家可以去github上fork或者下载

123456789101112131415161718192021222324252627282930313233343536373839404142434445
var Icon=require('react-native-vector-icons/FontAwesome'); export default class CheckBox extends React.Component{   static defaultProps = {      checked: false   };   static propTypes={     checked: React.PropTypes.bool,     onChange: React.PropTypes.func  };  constructor(props){     super(props);     this.state = {        checked: props.checked,     };  }  componentWillReceiveProps(nextProps) {      this.setState({        checked: nextProps.checked      });  }  onChange() {     this.setState({checked:!this.state.checked});  }  toggle(){     console.log("checkbox被点击了");     this.setState({checked:!this.state.checked});     this.props.onChange(this.state.checked);      }  render() {    var source = "square-o";    if(this.state.checked){      source = "check-square-o";    }    var container = (      <View style={styles.container}>        <Icon name={source} size={16} style={styles.checkbox} color="#00B4F7" ></Icon>      </View>    );    return (      <TouchableHighlight ref="checkbox" onPress={this.toggle.bind(this)} underlayColor='white'>        {container}      </TouchableHighlight>    )  }}

代码说明 :其实上面这段代码读起来应该没什么难度,定义了一个checked属性和一个回调的onChange事件,当点击TouchableHighlight时,调用toggle事件去改变当前checkbox的checked状态!

checkbox在ListView中的应用

介绍了如何封装一个checkbox组件,因此我们可以在其他的组件中灵活的去调用自己封装的组件,接下来我们看看checkbox如何在列表中展现,如何拿到checkbox选中的值?
在此之前,我们需要在组件顶部导入checkbox这个组件!

1
import CheckBox from './common/checkbox';

ListView 初始化

我们在render方法中 初始化listview

12345678910111213141516
<View style={styles.container}>    <View style={{flex:1}}>     <ListView      dataSource={this.state.dataSource}      refreshControl={this.renderRefresher()}      renderRow={this.renderList.bind(this)}      initialListSize={20}      renderSeparator={this._renderSeparatorView}      style={styles.listView}/>      </View>     <View>         <TouchableHighlight  underlayColor='#c8c7cc' onPress={()=>this.SelectAll()}>          <View style={[styles.btn,{backgroundColor:"#00CEF9",color:"#000"}]}><Text>全选</Text></View>         </TouchableHighlight>      </View></View>

  • this.state.dataSource 是我们listview的数据源
  • this.renderRefresher() 是本地写的一个方法 用来指定listview下拉刷新需要调用的控件,详细请看RefreshControl这个原生组件
  • this.renderList 渲染每行所调用的方法,也是我们需要着重去理解的,一般数据的绘制基本就是靠这个方法了

renderRow 行数据渲染

123456789101112131415161718192021222324252627
initCheckBoxData(checkbox){          if(checkbox!=null){    CheckBoxData.push(checkbox);    }}renderList(rowData,rowID) {  return (       <View style={styles.listRow} >           <View>           <CheckBox             ref={(c)=>this.initCheckBoxData(c)}             label=""             checked={false}             value={rowID}             style={styles.check}             onChange={(checked) => this.checkSelect(checked,rowID)} />             </View>             <View style={styles.rightContainer}>                 <Text style={styles.title}>{rowData.title}</Text>                 <Text style={styles.normal}>{rowData.desc}</Text>                 <Text style={styles.normal}>时间:{rowData.pubDate}</Text>                 <Text style={styles.normal}>来源:{rowData.source}</Text>             </View>         </View>     ); }

这个方法用来渲染每行数据,并提供了行对象和行索引,这里我做的是一个新闻列表。展示了新闻标题,描述,时间,来源等字段的展现,最左侧就是一个复选框,我们看到了 <CheckBox /> 这样的自定义组件出现在行数据中,为它指定了 onChange事件、value值绑定、checked默认值及ref输出当前对象,所以 initCheckBoxData 这个方法的作用就是将当前对象保存在一个共有的数组里面,全选的时候可以拿到每行的 Checkbox对象,并调用它自身的方法和属性。
干说了大半天,我们还是来看看效果图,界面比较丑,没有美化,望体谅哦…

结合listview展现checkbox结合listview展现checkbox

checkbox全选及单选的原理

  • 单选
    checkbox 本身外层包裹了一层 TouchableHighlight,TouchableHighlight设置了onPress事件,因此会去改变state里checked的状态,从而重新渲染当前checkbox,同时toggle事件里,调用了回调的onChange函数,将改变的值回传给前端的 checkSelect方法 onChange={(checked) => this.checkSelect(checked,rowID)}

    12345
    checkSelect(checked,id){  console.log(checked+",,,,"+id);         }
  • 多选
    多选这里调用了SelectAll 这个方法,说这个方法之前,我先说说 Ref 属性的作用,这个属性的官方解释是:允许你引用 render() 返回的相应的支撑实例( backing instance ),这样就可以确保在任何时间总是拿到正确的实例。通俗点说抛出一个引用接口,供外面的对象去访问这个实例。

因此上面listview里渲染时,我们申明了一个 全局变量 var CheckBoxData={],通过ref 将当前对象全部push到CheckBoxData变量中。这样为后面全选时做准备,下面看看具体全选的方法:

12345678
SelectAll(){for (var i = 0; i < CheckBoxData.length; i++) {   if(CheckBoxData[i]!=null){   console.log(CheckBoxData[i]);       CheckBoxData[i].onChange();   }}}

循环去变量CheckBoxData数组,并调用它自身的方法 onChange 去改变state里checked的状态,达到重新渲染的目的。我们在控制台输出看看 checkbox这个对象:

一句话:全选的实现无非就是拿到所有的checkbox对象,然后调用它自身的onChange事件 去改变state状态

checkbox的取值

取值就非常简单了,我们初始化的时候,为checkbox每个对象绑定了value值。
循环CheckBoxData这个数组时,我们可以拿到每个checkbox state里的checked状态,也能拿到props里的value值,从而知道哪些checkbox被选中了,值是多少!

checkbox组件 github地址 :传送门

0 0
原创粉丝点击