这次给大家分享一下 React中 ListView这个组件以及全选和单选按钮的封装使用。当然核心部分还是讲解自定义封装的 checkbox 组件!
React 有一个优势就是组件的复用性特别高,在原生组件中,官方并没有向我们提供checkbox这样的多选或单选的组件,因此需要我们自己去封装。
https://github.com/crazycodeboy/react-native-check-box
http://www.cnblogs.com/huangjialin/p/6180200.html
若我们需要在列表的右侧展现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 |
图片方式
这种就比较简单了,直接用原生的Image
组件去加载本地的资源图片就可以了,设计好checkbox 选中和未选中两张图片,通过state去切换图片的source属性。
1 2 3 4 5 |
var sourceUrl = require('image!selected'); if(this.state.checked){ sourceUrl = require('image!unselected'); } |
这里组件的编码,我暂时用的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 = ( |
代码说明 :其实上面这段代码读起来应该没什么难度,定义了一个checked属性和一个回调的onChange事件,当点击TouchableHighlight时,调用toggle事件去改变当前checkbox的checked状态!
介绍了如何封装一个checkbox组件,因此我们可以在其他的组件中灵活的去调用自己封装的组件,接下来我们看看checkbox如何在列表中展现,如何拿到checkbox选中的值?
在此之前,我们需要在组件顶部导入checkbox这个组件!
1
|
import CheckBox from './common/checkbox';
|
我们在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>
|
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 ( |
这个方法用来渲染每行数据,并提供了行对象和行索引,这里我做的是一个新闻列表。展示了新闻标题,描述,时间,来源等字段的展现,最左侧就是一个复选框,我们看到了
这样的自定义组件出现在行数据中,为它指定了 onChange事件、value值绑定、checked默认值及ref输出当前对象,所以 initCheckBoxData
这个方法的作用就是将当前对象保存在一个共有的数组里面,全选的时候可以拿到每行的 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每个对象绑定了value值。
循环CheckBoxData这个数组时,我们可以拿到每个checkbox state里的checked状态,也能拿到props里的value值,从而知道哪些checkbox被选中了,值是多少!
checkbox组件 github地址 :传送门