React-Native 中自定义checkbox组件

这次给大家分享一下 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的方式去安装 字体图标的依赖包,传送门 点我点我

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

    1
    2
    3
    4
    5
    
    var sourceUrl = require('image!selected');
    if(this.state.checked){
      sourceUrl = require('image!unselected');
    }
    source={sourceUrl}>
    
组件核心代码

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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 = (
      
        
      
    );
    return (
      
        {container}
      
    )
  }
}

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

checkbox在ListView中的应用

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

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

ListView 初始化

我们在render方法中 初始化listview

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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 行数据渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
initCheckBoxData(checkbox){
        
  if(checkbox!=null){
    CheckBoxData.push(checkbox);  
  }
}
renderList(rowData,rowID) {
  return (
        >
           
           
             ref={(c)=>this.initCheckBoxData(c)}
             label=""
             checked={false}
             value={rowID}
             style={styles.check}
             onChange={(checked) => this.checkSelect(checked,rowID)} />
             
             {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>
             
           
   );
 }

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

结合listview展现checkbox

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

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

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

1
2
3
4
5
6
7
8
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地址 :传送门

你可能感兴趣的:(】)