初探React-Native(二)代码篇

作者: 叫我马小帅 | 来源:发表于2018-01-25 16:28 被阅读70次

    撸了几天代码,iOS项目中集成RN页面还算简单,主要是互相之间的通讯,现在开始撸代码啦,
    直接上干货!

    1.iOS项目于RN之间互相的通讯

    iOS向RN页面发送数据,只能发送字典奥!!!

    iOS向RN页面发送数据

    在RN界面接收后就可以直接使用啦!


    接收并使用

    RN向iOS发送数据

    iOS项目中先创建一个类,并继承协议


    .m文件
    .h文件

    在RN文件中,声明NativeModules


    NativeModules声明

    其中CalendarManager要和iOS项目的类名一模一样!


    发送字符串

    之所以发送加载结束是因为我在iOS项目中添加了HUD蒙版,等RN页面的数据加载完成之后,发送加载结束给iOS项目,然后清除蒙版,但是这里有个小坑,下文说

    发送字典数据

    这样就可以RN传值给iOS了,大家可以试一试,好了,现在要说一下坑了,由于本人懒癌发作,脑抽的没有新建类,而是直接在ViewController中直接继承了协议,机智的我发现一样可以NSLog()打印出数据,然后我就直接操作 [HUD removeFromSuperview]; 发现取消不了HUD,打印HUD发现为null!

    可以接收数据,但是并改不了样式,哪怕加主线程
    谷歌到的原因
    解决方式还是老老实实的新创建类,然后用通知的方式进行更改吧 image.png
    要放在主线程中奥!

    2.RN中的列表ListView,包括下拉刷新上拉加载和网络请求

    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      View,
      Image,
      ListView,
      Text,
      TouchableOpacity,
      AlertIOS,
      NativeModules,
      RefreshControl,
      ActivityIndicator,
      Dimensions
    } from 'react-native';
    
    // 与iOS端通讯
    var CalendarManager = NativeModules.CalendarManager;
    
    // 声明空数组
    var demoList = [];
    
    // 获取全屏宽和高
    var {width, height} = Dimensions.get('window');  
    
    
    class ZhongShiMedia extends Component {
    
    
      constructor(props) {
        super(props);
        var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    
        this.state = {
          dataSource: ds.cloneWithRows(demoList),
          bigImg:'',
          page:0,
          isLoadingTail: false,  //是否显示下拉加载的动画,没有数据了返回ture择不显示下拉动画
          isRefreshing: false,  // 是否隐藏上拉
          first:false,  //因为第一次进入时_endReached也会走,为false让他第一次不执行网络请求方法
        };
    
        this.fetchData(false);
    
      }
    
    
    
      render() {
    
    
        return (
         <View style={styles.container}>
    
         <ListView
         dataSource={this.state.dataSource}
         contentContainerStyle={styles.grid}  
          renderHeader={this._renderHeader.bind(this)}  // 添加头视图
          renderRow={this._renderRow.bind(this)}
            renderFooter={() => this._renderFooter()}   //尾视图用来显示加载图标
            onEndReachedThreshold={1}      //显示尾视图就执行加载
            onEndReached={() => this._endReached()}
    
            refreshControl={
              <RefreshControl
                refreshing={this.state.isRefreshing} // 是否显示下拉舒心的动画
                onRefresh={() => this._onRefresh()}/>
              }
    
              />         
              </View>
              )
    
      }
      fetchData(isLoadMore) {
    
        if (isLoadMore) {
        // 加载
        this.state.page = this.state.page + 1;
    }else{
    
        //刷新
      this.state.page = 1;
    
    }
    
    
    
    let  page = this.state.page ;
    
    console.log('++++++' + page);
    
    //网络请求方法
    let url = 'http://pulandian.crhclub.com/attractionWebService.ashx?action=getAttractionInfoListRenqi&pageSize=10&page=' + page ;
    fetch(url, {
      method: 'GET',
      headers: {},
    })
    
    .then((response) => response.json())
    .then((responseData) => {
    
    // 如果有数据
      if (responseData.zhihuijinshi.length != 0) {
    
       if (isLoadMore) {
        // 加载
      demoList = demoList.concat(responseData.zhihuijinshi);
    
    }else{
    
        //刷新
      demoList = [];
      demoList = demoList.concat(responseData.zhihuijinshi);
    
    }
    }else{
      // 没有数据后,就不在执行下拉刷新的动画
      this.setState({
        isLoadingTail: true
      });
    }
    
    //修改数据和UI
    this.setState({
    
     dataSource: this.state.dataSource.cloneWithRows(demoList),
    
     bigImg:responseData.advert[0].imgUrl,
     isRefreshing: false,
    
    });
    //发送iOS端,取消HUD的动画
    CalendarManager.addEventOne('加载结束')
    
    })
    
    .catch((error) => {
      callback(error);
    });
    
    
    }
    
    
    // 上拉刷新的方法
    _onRefresh = () => {
    
     this.setState({
      isRefreshing: true,
    });
     this.fetchData(false);
    }
    
    //下拉刷新的方法
    _endReached = () => {
        // 防止第一次执行
        if(!this.state.first) {
         this.setState({
          first: true,
        });
         return
       }
        // 获取数据
        this.fetchData( true);
      }
    
    
    
      _renderFooter = () => {
    
        //没数据了则不显示动画
        if(this.state.isLoadingTail == true) {
    
         return <View style={{marginVertical:0}}/>
       }
    
        // 加载动画
        return (<ActivityIndicator style={{ marginVertical:20 }}/>);
      }
    
    
    // 头视图
      _renderHeader(){
        return ( <Image source={{uri:this.state.bigImg}} style={styles.hadImg} /> );
      }
    
    // cell  的布局
      _renderRow(rowData, sectionid, rowid) {  
        return (
         <TouchableOpacity activeOpacity={0.5} onPress={()=>{CalendarManager.addEventTwo({Id:rowData.id,title:rowData.title})}}>  
         <View style={styles.itemLayout}>
    
         <Image   defaultSource={{uri:'icon'}} source={{uri:rowData.imgurl}} style={styles.imageeee} /> 
    
         <View style={styles.rightSty}>
    
         <Text style={styles.titleSty}>{rowData.title}</Text>
         <Text style={styles.addressSty}>{rowData.address}</Text>
    
         </View>
         </View>
         <View style={styles.xian}></View>
         </TouchableOpacity>  
         );  
      }  
    
    
    }
    
    
    
     const styles = StyleSheet.create({
        container: {   //根View样式
          marginTop:64,
          flex: 1,
            backgroundColor: '#F6F6F6'
          },
          imageeee:{
    
            height:100,
    
            marginLeft:15,
            marginTop:10,
            flex:0.4,
            backgroundColor: '#63BAE0'
          }, 
    
          rightSty:{
            flex:0.6,
            backgroundColor: '#F6F6F6'
    
          },
    
    
          hadImg:{
    
            flex:1,
            height:150,
            resizeMode:'stretch',
          },
    
          titleSty:{
            marginTop:10,
            marginLeft:15,
            width:width * 0.5,
            height:20,
            fontSize: 17,
    
          },
          addressSty:{
            marginTop:10,
            marginLeft:15,
            width:width * 0.5,
    
          },
          xian:{
            width:width,
            height:1,
            backgroundColor:'#272822',
            marginTop:10,
          },
    
          itemLayout:{  
            flex:1,  
            flexDirection:'row',
            flexWrap:'wrap',
        backgroundColor:'#F6F6F6',
      }, 
    
    });
    
    
    
    //  项目名要有所对应
    AppRegistry.registerComponent('ZhongShiMedia', () => ZhongShiMedia);
    
    

    (xianView那个就是创建一条线,可以用 borderStyle:'solid',
    borderBottomWidth:1,
    borderBottomColor:'gray', 这个属性替代,不要像我一样low,这些代码可复制粘贴直接使用,备注写的也还可以,喜欢给点个赞,如果有问题,可以联系我)

    以下是个人理解的RN布局

    RN布局主要是操作父类,在一个<View></View>中View是父类,通过样式代码控制其子类是横向布局还是纵向布局
    flexDirection:column 纵向 row 横向
    然后可以再里面在通过另一个<View></View>来重新控制其横向还是纵向,但是必须是View,ScrollView行不行没有试,不过<Text>和<Image/>是不行的
    不过其子类可以用alignSelf这个属性
    RN中没有css的浮动属性,不过有绝对定位和相对定位

    3.RN中加载webView

    
                  <WebView bounces={false}
                    scalesPageToFit={true}
                    scrollEnabled={false}
                     onLoadEnd={this.onLoadEnd}
                    source={{uri:'https://www.baidu.com',method: 'GET'}}
                    style={styles.webSty}>
                    
                  </WebView>
    

    搞完了iOS中集成RN布局,又玩了会纯RN项目,这个RN项目也是好多坑呀!!!我捞干的长话短说吧

    1.tabBar项目框架的搭建

    首先RN要集成一些第三方框架,而RN的关于tabBar的框架有TabNavigator和react-navigation
    安装第三方框架的方法

    安装:npm install react-navigation --save
    查看:npm view react-navigation
    删除:npm rm react-navigation --save
    
    

    安装TabNavigator

    npm install react-native-tab-navigator --save
    

    安装react-navigation

    npm install react-navigation --save
    

    为什么要安装第三方框架呢,因为第三方框架安卓和iOS可以通用!
    以上两个框架我都试了,我推荐使用react-navigation,因为到二级页面后他可以隐藏tabBar,
    而TabNavigator没有隐藏的方法,只能动态改变TabBar的高度,也可能是我的方法有问题,才导致以下的Bug


    如果有解决方法告诉我一下

    react-navigation框架的集成....懒癌又犯了!主要是集成的代码太多,涉及多个页面,Demo还没写好,想要的留言吧,或者加我QQ1002547276,可以发个小项目给你

    这是集成的部分代码

    2.RN中创建轮播图
    RN中主流的轮播图框架也有两个react-native-swiper 和 react-native-viewpager

    这两个框架我同样都集成了,先说react-native-viewpager
    安装react-native-viewpager

      npm install react-native-viewpager --save
    

    项目中导入import ViewPager from 'react-native-viewpager';


    image.png

    但是这时候运行你会发现可恶的红色出现了
    unddefined is not an object(evaluating ‘React.propTypes.func’)

    4CB009D5DC235BB97D8FE345EB7F68AD.png

    因为...有个库不用了,详情自己百度吧,这不重要,俺们来干的,上解决办法

    进入到他的代码位置


    image.png ViewPager.js文件修改 DefaultViewPageIndicator.js文件修改 DefaultViewPageIndicator.js文件修改

    这样就解决啦,可以畅快的用react-native-viewpager了
    集成代码

    import React, { Component ,PropTypes} from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      Dimensions,
      Image
    } from 'react-native';
    import ViewPager from 'react-native-viewpager';
    
    var deviceWidth = Dimensions.get('window').width;
    
    var BANNER_IMGS = [
      'https://images.unsplash.com/photo-1441742917377-57f78ee0e582?h=1024',
      'https://images.unsplash.com/photo-1441716844725-09cedc13a4e7?h=1024',
      'https://images.unsplash.com/photo-1441448770220-76743f9e6af6?h=1024',
      'https://images.unsplash.com/photo-1441260038675-7329ab4cc264?h=1024',
      'https://images.unsplash.com/photo-1441126270775-739547c8680c?h=1024',
      'https://images.unsplash.com/photo-1440964829947-ca3277bd37f8?h=1024',
      'https://images.unsplash.com/photo-1440847899694-90043f91c7f9?h=1024'
    ];
    
    export default class HomePage extends Component {
    
      constructor(props) {  
            super(props);  
            // 用于构建DataSource对象  
            var dataSource = new ViewPager.DataSource({  
                pageHasChanged: (p1, p2) => p1 !== p2,  
            });  
            // 实际的DataSources存放在state中  
            this.state = {  
                dataSource: dataSource.cloneWithPages(BANNER_IMGS)  
            }  
        }  
      
        _renderPage(data, pageID) {  
            return (  
                <Image  
                    source={{uri:data}}  
                    style={styles.page}/>  
            );  
        }  
    
    
      render() {
        return (
                <View style={styles.container}>  
    
       <ViewPager  
                        style={{height:130}}  
                        dataSource={this.state.dataSource}  
                        renderPage={this._renderPage}  
                        isLoop={true}  
                        autoPlay={true}
                        />  
                                    </View>  
    
    
        );
      }
    
    }
    
    
    var styles = StyleSheet.create({
    
        container: {  
            flex: 1,  
            flexDirection: 'row',  
            alignItems: 'flex-start',  
            backgroundColor:'#999999',  
        },  
        page: {  
            width: deviceWidth,//设备宽(只是一种实现,此处多余)  
            height: 130,  
            resizeMode: 'stretch'  
        },  
    
    
    });
    
    
    

    你以为这就结束了? 不!!!


    小点点有问题

    这个控件的page点有问题,看到这一通集成的我已经崩溃了,不过可以在样式中添加renderPageIndicator={false} 来隐藏点点,不过我已经放弃这个控件了,如果有解决方法请留言或者私聊我!

    下面就来看看react-native-swiper,首先先来说我为什么没有第一个选择这个框架,因为百度查到的react-native-swiper的资料都是


    image.png image.png

    可以看出来,他们都是固定写死个数的<Image/>,实际开发中,要根据后台返回的数据来创建不同个数<Image/>,所有就要根据后台传的数组,动态创建<Image/>

    动态创建控件

    有了这个,剩下的就简单啦

    安装 react-native-swiper

    npm i react-native-swiper --save
    
    
    import React, { Component ,PropTypes} from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      Dimensions,
      Image
    } from 'react-native';
    import Swiper from 'react-native-swiper';
    
    var deviceWidth = Dimensions.get('window').width;
    
    var BANNER_IMGS = [
    'https://images.unsplash.com/photo-1441742917377-57f78ee0e582?h=1024',
    'https://images.unsplash.com/photo-1441716844725-09cedc13a4e7?h=1024',
    'https://images.unsplash.com/photo-1441448770220-76743f9e6af6?h=1024',
    'https://images.unsplash.com/photo-1441260038675-7329ab4cc264?h=1024',
    'https://images.unsplash.com/photo-1441126270775-739547c8680c?h=1024',
    'https://images.unsplash.com/photo-1440964829947-ca3277bd37f8?h=1024',
    'https://images.unsplash.com/photo-1440847899694-90043f91c7f9?h=1024'
    ];
    
    export default class HomePage extends Component {
    
      constructor(props) {  
        super(props);  
    
            // 实际的DataSources存放在state中  
            this.state = {  
            }  
          }  
    
    
          render() {
    
           var images = [];
    
           for (var i = 0; i < BANNER_IMGS.length; i++) {
            let view = (
    
              <View style={styles.slide}>
              <Image  
              source={{uri:BANNER_IMGS[i]}}  
              style={styles.page}/>  
              </View>  
    
              )
    
            images.push(view);
          }
    
    
          return (
            <View style={styles.lalal}>
    
            <Swiper style={styles.wrapper} height={200} horizontal={true} autoplay autoplayTimeout={1} 
    
    
                        // 修改点点的位置
                       // paginationStyle={{
                       //      bottom: 23, left: null, right: 10 
                       //  }}
                       >
                       {images}
                       </Swiper>
    
                       </View>
    
                       );
    
        }
      }
    
    
      var styles = StyleSheet.create({
    
        lalal:{
          height:200,
          width:deviceWidth,
    
          backgroundColor:'#FEFEFE',  
    
        },
        slide: {
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center',
          backgroundColor: '#9DD6EB'
        },
        page: {
          color: '#fff',
          width:deviceWidth,
          height:150,
        }
    
      });
    
    
    

    这两天撸的代码都在这里啦,RN之路还在慢慢探索中,有什么问题欢迎打扰,一起探讨

    生命不息,代码不止!码农一枚,请多点赞

    相关文章

      网友评论

        本文标题:初探React-Native(二)代码篇

        本文链接:https://www.haomeiwen.com/subject/vbwmaxtx.html