感觉有一段时间没写东西了,原因是从年初来了后,公司开展了移动端的业务,用的是
React-native
这个前端框架,所以这段时间一直很忙,需要去研究 React的Api、语法、兼容性、难点突破等等。
这次给大家分享一下 React中 ListView这个组件以及全选和单选按钮的封装使用。当然核心部分还是讲解自定义封装的 checkbox 组件!
React 有一个优势就是组件的复用性特别高,在原生组件中,官方并没有向我们提供checkbox这样的多选或单选的组件,因此需要我们自己去封装。
checkbox组件封装
准备条件
若我们需要在列表的右侧展现checkbox那样的复选框,一般在网页中会有自带的checkbox标签元素,那在react中我们需要用图片或者字体图标来实现checkbox样式的显示,当然也可以通过样式来控制
字体图标方式
在此我们需要通过npm的方式去安装 字体图标的依赖包,传送门 点我点我1
2
3
4
5
6
7
8npm 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属性。1
2
3
4
5var sourceUrl = require('image!selected');
if(this.state.checked){
sourceUrl = require('image!unselected');
}
<Image source={sourceUrl}></Image>
组件核心代码
这里组件的编码,我暂时用的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
45var 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方法中 初始化listview1
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 | initCheckBoxData(checkbox){ |
这个方法用来渲染每行数据,并提供了行对象和行索引,这里我做的是一个新闻列表。展示了新闻标题,描述,时间,来源等字段的展现,最左侧就是一个复选框,我们看到了 <CheckBox />
这样的自定义组件出现在行数据中,为它指定了 onChange事件、value值绑定、checked默认值及ref输出当前对象,所以 initCheckBoxData
这个方法的作用就是将当前对象保存在一个共有的数组里面,全选的时候可以拿到每行的 Checkbox对象,并调用它自身的方法和属性。
干说了大半天,我们还是来看看效果图,界面比较丑,没有美化,望体谅哦…
checkbox全选及单选的原理
单选
checkbox 本身外层包裹了一层 TouchableHighlight,TouchableHighlight设置了onPress事件,因此会去改变state里checked的状态,从而重新渲染当前checkbox,同时toggle事件里,调用了回调的onChange函数,将改变的值回传给前端的 checkSelect方法onChange={(checked) => this.checkSelect(checked,rowID)}
1
2
3
4
5checkSelect(checked,id){
console.log(checked+",,,,"+id);
}多选
多选这里调用了SelectAll 这个方法,说这个方法之前,我先说说 Ref 属性的作用,这个属性的官方解释是:允许你引用 render() 返回的相应的支撑实例( backing instance ),这样就可以确保在任何时间总是拿到正确的实例。通俗点说抛出一个引用接口,供外面的对象去访问这个实例。
因此上面listview里渲染时,我们申明了一个 全局变量 var CheckBoxData={]
,通过ref 将当前对象全部push到CheckBoxData变量中。这样为后面全选时做准备,下面看看具体全选的方法:1
2
3
4
5
6
7
8SelectAll(){
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地址 :传送门
华丽的分割线
自定义封装组件就介绍到这里,我也不清楚是否讲清楚了,如有不懂的可加群或者加我微信或者留言!!