您的位置:首页 > Web前端 > React

react_native 项目实战 (4) 自定义分类 使用 CheckBox 以及 数据存储asyncStorage

2017-10-17 18:34 656 查看

使用CheckBox

先看下效果图引入CheckBox 第三方复选框react-native-check-boxnpm install react-native-check-box –save //两个横杠leftText 的Text 大写.又被坑了一次Checkboxhttp://www.searu.org/39207.html遇到的问题1, 点击后就隐藏了 解决: 更新react-native-check-box 到最新的 就好了 吐血这个问题我开始想自己写的 但想着自己写肯定费时费力 不甘心 各种找资料 还是找到了
"react-native-check-box": "^2.0.2",
npm install react-native-check-box –save 用这个命令 别用github上面的那个readmi说的命令真的坑啊2, checkbox 没有勾选 解决: 原因isChecked Checked 我的c是小写 ..其他的难点就是关于算法的问题了 主要是这几个Checkbox如何布局 大致说下把:定义一个views数组 里面装了所有的Checkbox每一行我包裹起来 包裹了两个checkbox 然后用views数组给push进去需要留出最后一样 通过判断奇数偶数 再把最后一行添加进去具体看代码把

AsyncStorage使用 进行数据存取

引用
import {AppRegistry,StyleSheet,Text,View,Image,TouchableOpacity,AsyncStorage} from 'react-native';
通过 setItem方法保存数据 key- value 形式
 AsyncStorage.setItem('custom_key', JSON.stringify(this.state.data)).then(() => this.refs.toast.show("保存成功"));
获取 getItem 方法获取数据
 AsyncStorage.getItem('custom_key').then(value => {//有用户数据,选中该选中CheckBoxif (value !== null) {// console.log(JSON.parse(value));this.setState({data: JSON.parse(value)});} else {this.setState({data: [{name: 'Android', checked: true},{name: 'IOS', checked: true},{name: 'React Native', checked: true},{name: 'Java', checked: true},{name: 'JS', checked: true}]});}});
下面上完成的代码
/*** Created by liuml on 2017/9/17.*/import React, {Component} from 'react';import {AppRegistry,StyleSheet,Text,View,Image,AsyncStorage,TouchableOpacity} from 'react-native';/*** 自定义分类页面*/import NavigationBar from '../compont/NavigationBar';import CheckBox from 'react-native-check-box';import Toast from "react-native-easy-toast"export default class CustomKeyPage extends Component {// 构造constructor(props) {super(props);// 初始状态this.state = {data: [{name: 'android', checked: true},{name: 'IOS', checked: false}]};}handleBack = () => {this.props.navigation.goBack();}getLeftBtn = () => {return <View style={{flexDirection: 'row', alignItems: 'center'}}><TouchableOpacityactiveOpacity={0.7}onPress={this.handleBack}><Image source={require('../../res/images/ic_arrow_back_white_36pt.png')}style={{width: 24, height: 24}}/></TouchableOpacity></View>;}getRightBtn = () => {return <View style={{flexDirection: 'row', alignItems: 'center'}}><TouchableOpacityonPress={this.handleSave}activeOpacity={0.7}><View style={{marginRight: 10}}><Text style={{fontSize: 16, color: '#FFF'}}>保存</Text></View></TouchableOpacity></View>;}//保存handleSave = () => {//http://lib.csdn.net/article/reactnative/43540   JSON.stringify 字符串转JSON//AsyncStorage是一个简单的、异步的、持久化的Key-Value存储系统AsyncStorage.setItem('custom_key', JSON.stringify(this.state.data)).then(() => this.refs.toast.show("保存成功"));// console.log(JSON.stringify(this.state.data));}//CheckBox 点击  有个疑问为什么在这里设置值就可以不用setState就改变item的checked,因为是这样调用的()=>this.handlerCBClick(item)handleClick = (item) => {// console.log("之前 " + item.checked);item.checked = !item.checked;// console.log("之后 " + item.checked);}//渲染CheckBox  这里item就是一个对象renderCheckBox = (item) => {// console.log(item);// console.log(item.name + ',' + item.checked);var leftText = item.name;return <CheckBoxstyle={{flex: 1, padding: 10}}onClick={() => this.handleClick(item)}leftText={item.name}isChecked={item.checked}unCheckedImage={<Image source={require('../../res/images/ic_check_box_outline_blank.png')}style={styles.checkbox}/>}checkedImage={<Image source={require('../../res/images/ic_check_box.png')} style={styles.checkbox}/>}/>}renderViews = () => {let len = this.state.data.length;var views = [];  //要绘制的所有多选框,装入views数组for (let i = 0, j = len - 2; i < j; i += 2) {views.push((<View key={`view_${i}`} style={{flexDirection: 'row'}}>{this.renderCheckBox(this.state.data[i])}{this.renderCheckBox(this.state.data[i + 1])}</View>));}//偶数个,剩下最后两个多选框//奇数个,剩下最后一个多选框views.push(<View key={`view_${len - 1}`} style={{flexDirection: 'row'}}>{len % 2 === 0 ? this.renderCheckBox(this.state.data[len - 2]) :<View style={{flex: 1, padding: 10}}></View>}{this.renderCheckBox(this.state.data[len - 1])}</View>);return views;}componentDidMount = () => {this.loadData();}loadData = () => {//加载本地数据AsyncStorage.getItem('custom_key').then(value => {//有用户数据,选中该选中CheckBoxif (value !== null) {// console.log(JSON.parse(value));this.setState({data: JSON.parse(value)});} else {this.setState({data: [{name: 'Android', checked: true},{name: 'IOS', checked: true},{name: 'React Native', checked: true},{name: 'Java', checked: true},{name: 'JS', checked: true}]});}});// console.log(this.state.data);}render() {return <View style={styles.container}><NavigationBartitle="自定义分类"rightButton={this.getRightBtn()}leftButton={this.getLeftBtn()}/><View style={{flexDirection: 'column'}}>{this.renderViews()}</View><Toast ref="toast"/></View>}}const styles = StyleSheet.create({container: {flex: 1},checkbox: {tintColor: '#63B8FF'}});
看看最终效果图其实这个第三方CheckBox 有个bug当属性变化时 并没有刷新状态 那么 需要我进入源码 让他属性变化时 刷新他的状态主要代码 进入源码后 加入下面的代码
    //当组件接收到新的属性值时被调用componentWillReceiveProps(nextProps) {//让状态跟着属性变化this.setState({isChecked:nextProps.isChecked});}
下面做一些完善 比对修改前后数据 弹出是否保存对话框

首页最热页面 读取保存的数据

首页的最热页面根据保存的分类读取数据
/*** Created by liuml on 2017/9/11.*/import React, {Component} from 'react';import {AppRegistry,StyleSheet,Text,View,Image,ListView,RefreshControl,TouchableOpacity,AsyncStorage}from 'react-native';import NavigationBar from "../compont/NavigationBar.js"import ScrollableTabView from "react-native-scrollable-tab-view"import ProjectRow from "../compont/ProjectRow"/*** 最热页面*/export default class PapularPage extends Component {// 构造constructor(props) {super(props);// 初始状态this.state = {languages: [{name: 'Android'},{name: 'IOS'},{name: 'React'},{name: 'Java'},{name: 'JS'}]};}getRightBtn = () => {return <View style={{flexDirection: 'row', alignItems: 'center'}}><TouchableOpacity activeOpacity={0.7}><Image source={require('../../res/images/ic_search_white_48pt.png')}style={{width: 24, height: 24}}></Image></TouchableOpacity><TouchableOpacity activeOpacity={0.7}><Image source={require('../../res/images/ic_more_vert_white_48pt.png')}style={{width: 24, height: 24}}></Image></TouchableOpacity></View>}loadLanguages = () => {// AsyncStorage.clear();AsyncStorage.getItem('custom_key').then((value) => {console.log("读取的: " + value);console.log("读取的: " + JSON.parse(value));if (value != null) {this.setState({languages: JSON.parse(value)});}});}componentDidMount() {this.loadLanguages();}render() {return <View style={styles.container}><NavigationBarrightButton={this.getRightBtn()}title="热门"/><ScrollableTabViewtabBarBackgroundColor="#63B8FF"tabBarActiveTextColor="#FFF"tabBarInactiveTextColor="#F5FFFA"tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}>{this.state.languages.map((item, i) => {console.log(item);return (item.checked == undefined || item.checked ?<PopularTab key={`tab${i}`} tabLabel={item.name}/> : null)})}</ScrollableTabView></View>}}class PopularTab extends Component {//这里是Tab 的名字static defaultProps = {tabLabel: 'android',}// 构造constructor(props) {super(props);// 初始状态this.state = {dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),//是一个优化,节省无用的UI渲染 判断前后数据是否改变 如果改变就更新isLoading: true};}/*componentDidMount() {/!*this.setState({dataSource: this.state.dataSource.cloneWithRows(['first', 'second', 'three'])})*!/this.loadData();};*///和上面一样的效果  页面加载完成后加载数据componentDidMount = () => {this.loadData();}//渲染ListView的每一行renderRow = (obj) => {return <ProjectRow item={obj}></ProjectRow>// return <Text>{obj.full_name}</Text>}//加载数据loadData = () => {this.setState({isLoading: true});fetch(`https://api.github.com/search/repositories?q=${this.props.tabLabel}&sort=stars`).then(response => response.json()) //服务器响应response对象,继续变成json对象.then(json => {//更新dataSourcethis.setState({dataSource: this.state.dataSource.cloneWithRows(json.items),isLoading: false,});}).catch((error) => {console.error(error);}).done();}handleRefresh = () => {this.loadData();}render() {return <View style={styles.container}><ListViewdataSource={this.state.dataSource}renderRow={this.renderRow}refreshControl={<RefreshControlrefreshing={this.state.isLoading}tintColor="#63B8FF"title="正在加载..."titleColor="#63B8FF"colors={['#63B8FF']}/>}></ListView></View>}}const styles = StyleSheet.create({container: {flex: 1}});
主要的两段代码读取本地保存的数据
componentDidMount() {this.loadLanguages();}loadLanguages = () => {// AsyncStorage.clear();AsyncStorage.getItem('custom_key').then((value) => {console.log("读取的: " + value);console.log("读取的: " + JSON.parse(value));if (value != null) {this.setState({languages: JSON.parse(value)});}});}
根据本地数据显示
<ScrollableTabViewtabBarBackgroundColor="#63B8FF"tabBarActiveTextColor="#FFF"tabBarInactiveTextColor="#F5FFFA"tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}>{this.state.languages.map((item, i) => {console.log(item);return (item.checked == undefined || item.checked ?<PopularTab key={`tab${i}`} tabLabel={item.name}/> : null)})}</ScrollableTabView>
效果图得注意下我这里做的是重新加载才更新了顶部标题,后面会做下不重新加载,就更新首页的最热标签栏.下面做下分类排序页面

分类排序

效果图分类排序 用到了第三方组件安装命令npm install react-native-sortable-listview –save分类页面代码
/*** Created by liuml on 2017/10/22.*/import React, {Component} from 'react';import {AppRegistry,StyleSheet,Text,View,Image,TouchableOpacity,TouchableHighlight,AsyncStorage,} from 'react-native';import NavigationBar from "../compoent/NavigationBar";import SortableListView from "react-native-sortable-listview";export default class SortKeyPage extends Component {// 构造constructor(props) {super(props);// 初始状态this.state = {data: [],};}doBack = () => {this.props.navigation.goBack();}getLeftBtn = () => {return <View style={{flexDirection: 'row', alignItems: 'center'}}><TouchableOpacityactiveOpacity={0.7}onPress={this.doBack}><Image source={require('../../res/images/ic_arrow_back_white_36pt.png')}style={{width: 24, height: 24}}/></TouchableOpacity></View>;}componentDidMount() {AsyncStorage.getItem("custom_key").then(value => {if (value != null) {//只获取checked为true语言,进行排序  forEach 不会返回一个数组 而map会返回一个数组let d = [];JSON.parse(value).forEach((item) => {if (item.checked) {d.push(item);}})this.setState({data: d});var myorder = Object.keys(this.state.data); //Array of keys}})}render() {return <View style={styles.container}><NavigationBartitle="语言分类排序"leftButton={this.getLeftBtn()}/><SortableListViewdata={this.state.data}order={Object.keys(this.state.data)}rowActivationTime="10"renderRow={row => <RowComponent data={row}/>}onRowMoved={e => {this.state.data.splice(e.to, 0, this.state.data.splice(e.from, 1)[0]);this.forceUpdate();}}/></View>}}//https://github.com/deanmcpherson/react-native-sortable-listview/blob/master/Sortable/example.js 这里是SortableListView github地址 示例代码class RowComponent extends Component {static defaultProps = {data: {name: ""}};render() {return <TouchableHighlightunderlayColor="#EEE"style={styles.item}{...this.props.sortHandlers}><View style={{flexDirection: 'row', paddingLeft: 10}}><Image source={require('../../res/images/ic_sort.png')} style={styles.image}/><Text>{this.props.data.name}</Text></View></TouchableHighlight>}}const styles = StyleSheet.create({container: {flex: 1},item: {backgroundColor: '#F8F8F8',borderBottomWidth: 1,borderColor: '#EEE',height: 50,justifyContent: 'center'},image: {width: 16,height: 16,marginRight: 10,tintColor: '#63B8FF'}});
项目地址https://github.com/liudao01/ReactNativeProject
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐