react_native 项目实战 (5) DeviceEventEmitter 使用 ,webview 使用 react navigation进行参数传递
来源:互联网 发布:mac 升级后切换花屏 编辑:程序博客网 时间:2024/06/08 11:57
今天 2017.10.26 我把android studio升级成了3.0 结果RN项目 各种问题
其他问题我用android studio 3.0 把项目打开一遍就好了 但是使用rn run android的时候 有个gradle 3.0一直下载不下来
说缺少3.0
解决:
buildscript { repositories { jcenter() maven { url 'https://maven.google.com' } } dependencies { classpath 'com.android.tools.build:gradle:3.0.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}
我是翻墙了的 不翻墙 不清楚能不能下载
分类排序数据存取
分类选择页面和首页的数据获取,存取的数据结构是:
[ {"name":"Android","checked":true}, {"name":"IOS","checked":false}, {"name":"React","checked":true}, {"name":"Java","checked":true}, {"name":"JS","checked":true}]
分类排序的页面存取的数据结构是
这里取出的值 checked 肯定是true
“name”:”Android”
“name”:”IOS”
“name”:”IOS”
举个例子
//原始数组var originalArray = [ {name:'Android',checked:true}, {name:'IOS',checked:false}, {name:'React',checked:true}, {name:'Java',checked:false}, {name:'JS',checked:true}, {name:'Python',checked:false}];//排序后的数组var sortedArray = [ {name:'JS',checked:true}, {name:'React',checked:true}, {name:'Android',checked:true}];
当分类排序过后 需要把分类排序后的数据 再次存入通用的分类数据结构.
图例:
下面是js代码
/** * 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";import popular_def_lans from "../../res/data/popular_def_lans.json"import Toast from "react-native-easy-toast"/** * 分类排序页面 */export default class SortKeyPage extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { originData: popular_def_lans, data: [], }; //初始化数据 把所有选中的数据放入进去 this.state.originData.forEach((item => { if (item.checked) { this.state.data.push(item) } })) } doBack = () => { this.props.navigation.goBack(); } //保存 doSave = () => { //原始数组 var originArray = this.state.originData; //排序后的数组 var sortedArray = this.state.data; //要保存的数组 var savedArray = []; //i用来遍历originalArray //j用来遍历sortedArray for (var i = 0, j = 0; i < originArray.length; i++) { var item = originArray[i]; if (item.checked) { savedArray[i] = sortedArray[j]; j++; } else { savedArray[i] = item; } } console.log("保存读取: "); console.log(savedArray); AsyncStorage.setItem("custom_key", JSON.stringify(savedArray)) .then(() => { this.refs.toast.show("保存成功"); this.doBack(); }) } //保存 handleSave = () => { this.doSave(); } getLeftBtn = () => { return <View style={{flexDirection: 'row', alignItems: 'center'}}> <TouchableOpacity activeOpacity={0.7} onPress={this.doBack}> <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'}}> <TouchableOpacity onPress={this.handleSave} activeOpacity={0.7}> <View style={{marginRight: 10}}> <Text style={{fontSize: 16, color: '#FFF'}}>保存</Text> </View> </TouchableOpacity> </View>; } componentDidMount() { AsyncStorage.getItem("custom_key") .then(value => { console.log("进入读取: "); console.log(value); if (value != null) { //只获取checked为true语言,进行排序 forEach 不会返回一个数组 而map会返回一个数组 let d = []; let origin = JSON.parse(value); origin.forEach((item) => { if (item.checked) { d.push(item); } }) // this.setState({data: d}); // var myorder = Object.keys(this.state.data); //Array of keys this.setState({originData: origin, data: d}); } }) } render() { //http://www.w3school.com.cn/jsref/jsref_splice.asp splice方法的使用 return <View style={styles.container}> <NavigationBar title="语言分类排序" rightButton={this.getRightBtn()} leftButton={this.getLeftBtn()}/> <SortableListView data={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(); }} /> <Toast ref="toast"/> </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 <TouchableHighlight underlayColor="#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' }});
可以看到 我主要的代码 就在返回保存的时候doSave 方法里面 进行排序存储
下面是效果:
首页实时更新 使用 DeviceEventEmitter 发送接收事件
现在首页是我通过手动刷新js 才更新界面 现在需要 自动刷新
DeviceEventEmitter 使用方法
第一步 添加监听
DeviceEventEmitter.addListener(‘名称’,(events) ={使用数据events});
第二部 发送数据
DeviceEventEmitter.emit(‘自定义名称’,发送数据);
这样就可以了
那么现在我写一下 在首页刷新数据的监听
//路由const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'Home'}) ]}) componentDidMount() { this.listener = DeviceEventEmitter.addListener('HOMEPAGE_RELOAD', (n) => { //主页重新加载数据 console.log("主页重新加载数据"); //跳转到新的场景,并且重置整个路由栈 this.props.navigation.dispatch(resetAction); // this.props.navigation.resetTo({ // component:Homepage // }) }) } componentWillUnmount() { //移除监听 this.listener.remove(); }
然后在保存的时候发送数据
//保存 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)); this.doBack(); DeviceEventEmitter.emit("HOMEPAGE_RELOAD","HomePage重新加载"); }
但是发现有个bug 如果在我的页面 跳转后 返回重新加载会报错 说是和 测量的问题有关..这个就先放放.
webview使用 项目详情页面
新建ProjectDetails.js 作为项目详情页面
在PapularPage页面 点击listview 的item 跳转 把item数据内的 title 和url 传到项目详情页面
//渲染ListView的每一行 renderRow = (obj) => { return <ProjectRow item={obj} onSelect={() => this.handleProjectSelect(obj)}> </ProjectRow> } handleProjectSelect = (obj) => { navigation('ProjectDetails', { params: { title: obj.full_name, url: obj.html_url }, }); }
注意这里是一个比较经典的 父控件 把方法传入 子控件 子控件 回调父控件.
上面在PapularPage页面 这个onSelect 属性传入子控件ProjectRow
render() { var item = this.props.item; return <TouchableOpacity activeOpacity={0.5} onPress={this.props.onSelect}> <View style={styles.container}> <Text style={styles.title}>{item.full_name}</Text> <Text style={styles.description}>{item.description}</Text> <View style={styles.bottom}> <View style={styles.bottomTextWrapper}> <Text>作者:</Text> {/* {console.log(item.owner.avatar_url)}*/} <Image style={{width: 22, height: 22}} source={{uri: item.owner.avatar_url}}/> </View> <View style={styles.bottomTextWrapper}> <Text>star:</Text> <Text>{item.stargazers_count}</Text> </View> <Image source={require("../../res/images/ic_unstar_transparent.png")} style={{width: 22, height: 22}}/> </View> </View> </TouchableOpacity> }
在子控件中 onPress={this.props.onSelect} 进行回调这样就有了点击事件
而且还防止了一个问题 . 我测试过 直接在外面父控件中 使用onpress调用
this.handleProjectSelect(obj)
这个方法 会直接调用 没有点击就会调用 因为 带上了括号 所有导致这个问题 .如果我使用子控件回调的方式 也就防止了这个问题…
下面写ProjectDetails.js 这个是详情页面 用了webveiw
/** * Created by liuml on 2017/10/26. */import React, {Component} from 'react';import { AppRegistry, StyleSheet, Text, View, Image, TouchableOpacity, WebView} from 'react-native';import NavigationBar from "../compoent/NavigationBar";export default class ProjectDetails extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { canGoBack: false }; } handleBack = () => { //如果网页能够返回 先返回网页 if (this.state.canGoBack) { this.refs.webview.goBack(); } else { this.doBack(); } } doBack = () => { this.props.navigation.goBack(); } getLeftBtn = () => { return <View style={{flexDirection: 'row', alignItems: 'center'}}> <TouchableOpacity activeOpacity={0.7} onPress={this.handleBack}> <Image source={require('../../res/images/ic_arrow_back_white_36pt.png')} style={{width: 24, height: 24}}/> </TouchableOpacity> </View>; } //监听状态改变 是否能够返回 handleNavStateChange = (s) => { this.setState({canGoBack: s.canGoBack}); } render() { const {state} = this.props.navigation; let title = state.params.params.title; let url = state.params.params.url; console.log("打印" + url); return ( <View style={styles.container}> <NavigationBar title={title} leftButton={this.getLeftBtn()}/> <WebView ref="webview" startInLoadingState={true} source={{uri: url}} onNavigationStateChange={this.handleNavStateChange} /> </View> ); }}const styles = StyleSheet.create({ container: { flex: 1 },})
有几个点
- 一个是使用react navigation 传递参数
- 一个是从react navigation 接受参数
- 一个是监听webveiw 是否可以返回
第一个点: 传递参数在上面 单独的点已经有了
第二个点: 接受参数
const {state} = this.props.navigation; let title = state.params.params.title; let url = state.params.params.url;
从props里面取出navigation 然后取出他的state 两层params 最后才是数据
第三个点: 监听webview是否返回 这里webview有个自己的属性onNavigationStateChange 我在属性上面添加了一个方法
//监听状态改变 是否能够返回 handleNavStateChange = (s) => { this.setState({canGoBack: s.canGoBack}); }
把是否可以返回加入state中 这样当点击返回箭头的时候可以进行判断
看下最终效果图
- react_native 项目实战 (5) DeviceEventEmitter 使用 ,webview 使用 react navigation进行参数传递
- react_native 项目实战 (6) 趋势页面 列表抽取 popover使用
- react-navigation Navigation使用
- ReactNative基础(五)使用react-navigation实现页面的跳转、参数的传递(StackNavigator)
- ReactNative基础(五)使用react-navigation实现页面的跳转、参数的传递(StackNavigator
- react-native使用react-navigation进行页面跳转导航
- react-navigation 简单使用
- react-navigation使用
- react-navigation使用技巧
- react-navigation使用
- react-navigation使用心得
- React Navigation基础使用
- react-navigation使用技巧
- react-navigation 使用详解
- react-navigation使用技巧
- react-navigation使用技巧
- react-navigation的使用
- react-navigation 使用详解
- 极差(贪心)
- linux 接收文件+调用python脚本
- NYOJ033蛇形填数
- Tasks、 activity 及 activity stack
- SVN使用简介
- react_native 项目实战 (5) DeviceEventEmitter 使用 ,webview 使用 react navigation进行参数传递
- 线性表
- 前端工作中的两点优化
- Android面试题汇总
- <详解>C语言实现程序跳转到绝对地址0x100000处执行
- Vue框架(一)
- 阿里云存储失败
- 移动端中弹框显示模型属性信息的实现方案
- Mybatis的$和#的区别