react-native学习

第一章

  1. 启动页
    1.进入启动页后,3S后进入main主页
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View,Image} from 'react-native';
type Props = {};
import Main from './Main';
export default class StartImage extends Component<Props> {
 componentDidMount(){
       setTimeout(()=>{this.props.navigator.replace({//替换路由
          component:Main,
       })},3000)
  }
  render() {
    return (
      <View style={styles.container}>
          <Image source={{uri:'startmage'}} style={styles.ImageStartStyle}/>
      </View>
    );
  }
}
 1. ****

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  ImageStartStyle:{
     flex:1
  }
});

登录界面
注册:

//注册按钮
 <TouchableOpacity onPress={this.Register} style={styles.buttonviewTwo}>
                            <Text style={styles.logintext}>注册</Text>
</TouchableOpacity>
//进入到注册
this.props.navigator.push({
          scene: Register,
      });
//注册界面:
用户名
使用的textinput标签,onchangetext,如果识别出是空字符,则会显示用户请输入用户名,如果识别出不是空字符,则不显示
onChangeText={name =>
                            this.setState({ name }, () => {
                                if (this.state.name === '') {
                                    this.setState({
                                        errorName: '请输入用户名'
                                    })
                                } else if (this.state.name !== '') {
                                    this.setState({
                                       errorName: ''
                                   })
                               }
                           })
                   }
密码
密码也有这个功能
确认密码
确认密码也有这个功能
当你在输入确认密码的时候,会跟密码这一栏进行比对,如果密码一致,则不会有任何的显示;如果密码不一致,则会显示出密码不一致。
onChangeText={password2 =>
                            this.setState({ password2 }, () => {
                                if (this.state.password2 !== this.state.password) {
                                    this.setState({
                                        errorPass2: '密码不一致'
                                    })
                                }
                                else if (this.state.password2 === this.state.password) {
                                    this.setState({
                                        errorPass2: ''
                                    })
                                }
                            })
                        }
注册按钮:
touchableopacity标签里面有一个disabled属性,该属性的作用就是确认是否存在错误信息,如果有错误信息则点击注册按钮无效,如果没有错误信息,则点击注册按钮有效
disabled={
                        this.state.errorName === '' &&
                        this.state.errorPass === '' &&
                        this.state.errorPass2 === ''
                            ? false
                            : true
                    }
onpress属性则就是把用户的用户名和密码发送至服务端
首先我会创建一个对象,里面存放数据,然后通过fetch将数据发送至服务端,
fetch('http://10.22.173.166:7700/users', {
            headers: {
                'content-type': 'application/json'
            },
            method: 'POST',
            cache: 'no-cache',
            mode: 'cors',
            body: JSON.stringify(newUser)
        })
发送至服务端以后,就会跟服务器端的数据库里面的数据进行比较,看此用户名和密码是否存在,如果存在,则会向客户端发送name already exists,表示用户已经存在,否则注册成功。
.then(res => res.json())
            .then(res => {
                if (res.name === 'name already exists') {
                    this.setState({
                        errorName: '用户已存在,请登录'
                    })
                }
                else
                {
                    alert("注册成功")
                }
            })
注册成功以后,则会自动调整到上一界面,this.props.navigator.pop()  
登录界面的话
就是将用户名和密码输入以后,点击登录按钮就会把数据封装成对象的形式传送至服务端,服务端会很数据库的数据 进行 比较,如果符合则登录成功,否则登录失败。
登录成功以后,就会跳转至主页
this.props.navigator.push({
          scene: Register,
      });    

2. 主页/TabNavigator底部导航
主页的this.state设置成了selectedTab:“首页”,然后在底部导航中如下selected属性,那默认显示就是显示首页。

<TabNavigator.Item  
                       selected={this.state.selectedTab==='首页'}
                       title='首页'
                       titleStyle={styles.tabText}
                       selectedTitleStyle={styles.selectedTabText}
                       renderIcon={()=><Image source={require('../images/index.png')} style={styles.icon}/>}
                       onPress={()=>this.setState({selectedTab:'首页'})}
                    >
                    <Loulannavigator navigator={this.props.navigator}/>
                    </TabNavigator.Item>
在首页你点击漏缆监测实时状态,this.props.navigator.push({
   component:ruqinnavigator
})
进入到漏缆监测实时状态以后,你就会看到一张地图,这个地图我用的是react-native-baidu-map这个插件,里面有mapview,maptypes,geolocation。首先你要在初始状态里面设置其地图的中心位置,地图的等级大小,地图的标识,然后你在该标签下引用:
<MapView 
         zoom={this.state.zoom}
         mapType={this.state.mapType}
         center={this.state.center}
         markers={this.state.markers}          
         style={styles.map}
       >
入侵点的获取:
我是通过安装import SocketIOClient from 'socket.io-client';
   var socketSend='http://10.22.173.166:2013';
   this.onReceivedMessage = this.onReceivedMessage.bind(this);
   this.socket = SocketIOClient(socketSend);
   this.socket.on('ruqin', this.onReceivedMessage);
   this.socket.on('ruqin2', this.onReceived);
这些是主要的功能
返回首页:this.props.navigator.push({component:Loulanindex})


3. 入侵告警记录/ListView的使用
首先listview要设置初始状态,设置数据的初始源。然后使用swiperlistview中的renderRow进行数据的加载显示 ,属性refreshControl进行刷新控制;属性renderHiddenRow进行隐藏行的显示(保存和删除);点击保存以后就会将相应的数据发送到后端保存到数据库;点击删除以后就会将相应相应的数据发送至后端将对应的数据进行删除操作 。

this.state = {
            datas:new ListView.DataSource({
                rowHasChanged: ((row1, row2) => row1 !== row2)
            }),
            isLoading:true,
            id:2,
        };
<SwipeListView
  dataSource={this.state.datas}
  renderRow={(movie,sectionID,rowID) => <MovieItem movie={movie} sectionID={sectionID} rowID={rowID} navigator{this.props.navigator}/>}
        refreshControl={<RefreshControl
              refreshing={this.state.isLoading}
              onRefresh={()=>this.onLoad()}
/>}
 enableEmptySections={true}
          renderHiddenRow={(data, rowMap) =>(
                  <View style={styles.rowBack}>
                  <TouchableOpacity style={[styles.backRightBtn, styles.backRightBtnLeft]} onPress={ _ => this.saveSectionRow(rowMap, data)}>
                  <Text style={styles.backTextWhite}>保存</Text>
                   </TouchableOpacity>
                   <TouchableOpacity data={data} style={[styles.backRightBtn, styles.backRightBtnRight]} onPress={ _ => this.deleteSectionRow(rowMap, data)}>
                            <Text style={styles.backTextWhite}>删除</Text>
                      </TouchableOpacity>
                    </View>
                  )}
                    rightOpenValue={-150}
 />

当你点击对应的信息的时候,就会加载详细内容(入侵经纬度,入侵时间,入侵距离),通过navigator.push中的params将数据传送过去

_onPressView(){
        const { navigator } = this.props;
        if(navigator) {
            navigator.push({
                name: 'MovieInfo',
                component: MovieInfo,
                params:{
                    intrulLng: this.props.movie.lng,
                    intrulLat:this.props.movie.lat,
                    intrulWarnTime:this.props.movie.warnTime,
                    intrulDataIntrul:this.props.movie.dataIntrul
                }
            });
        }
    }

数据传送过去以后,在其初始化中的state里面放置其传送过来的数据

 constructor(props){ 
        super(props);
        this.state={
            intrulLng:this.props.intrulLng,
            intrulLat:this.props.intrulLat,
            intrulWarnTime:this.props.intrulWarnTime,
            intrulDataIntrul:this.props.intrulDataIntrul,
            mayType: MapTypes.NORMAL,
            zoom: 21,
            center: {
                      longitude: 121.645052,
                      latitude: 29.909163
                    },
             markers: [{
                  longitude: 121.645052,
                  latitude: 29.909163,
                   title: "宁波大学"
                  }]
             }
    }
 然后将传送过来的数据中的经纬度作为其地图的中心坐标和标记

ListView
ListView组件是React Native中一个比较核心的组件,用途非常广,设计初衷就是用来高效的展示垂直滚动的列表数据
ListView继承了ScrollView的所有属性
使用步骤:
创建一个ListView.DataSource数据源,然后给它传递一个普通的数组数据
getInitialState(){
//初始化数据源(rowHasChanged是优化的一种手段,只有当r1!==r2的时候才会重新渲染)
var ds=new ListView.DataSource({rowHasChanged:(r1,r2)=>r1!==r2});
return{
dataSource:ds.cloneWithRows(['内容0‘,’内容1‘,’内容2‘,’内容3‘,’内容4‘,’内容5‘])
}
},
render(){
return(

//根据数据源实例化一个ListView
<ListView style={{backgroundColor:‘yellow’}}
//获取数据源
dataSource={this.state.dataSource}
//根据数据源创建一个Item
renderRow={this.renderRow}
/>

)
},
renderRow(rowData,sectionID,rowID){
return(
//实例化Item

<Text style={{backgroundColor:‘red’,height:44}}>
内容{rowData},在第{sectionID}组第{rowID}行

)}

首先,ListView需要数据源,那么我们就先来自定义一下数据源的Json数据

[
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"},
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"},
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"},
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"},
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"},
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"},
        {"title" : "icon", "img" : "icon"},
        {"title" : "lufei", "img" : "lufei"}
    ]

获取数据
var newData=require(’./Data/localData.json’)
初始化数据源

getInitialState(){
        var ds = new ListView.DataSource({rowHasChanged:(r1, r2) => r1 != r2});
            return{
                // 将获得的数组传递给dataSource
                dataSource : ds.cloneWithRows(newData)
        }
    },

接着就是根据数据源实例化ListView
视图部分

render(){
        return(
            <View style={styles.container}>
                <ListView
                    dataSource={this.state.dataSource}
                    renderRow={this.renderRow}
                />
            </View>
        );
    },

    // 返回一个Item
    renderRow(rowData){
        return(
            <View style={styles.itemStyle}>
                <Image source={{uri:rowData.img}} style={styles.imageStyle}/>
                <View style={styles.subItemStyle}>
                    <Text style={{marginTop:5, fontSize:17}}>{rowData.title}</Text>
                    <Text style={{marginBottom:5, fontSize:13, color:'green'}}>简介</Text>
                </View>
            </View>
        );
    }

ListView 九宫格布局实现
从上面可以看出,这个案例是为了实现类似CollectionView效果,通常情况下,ListView是纵向排列的而此案例我们需要它横向排列,那么就需要使用到上面提到的contentContainerStyle属性,向里面添加flexDirection:'row’和flexWrap:'wrap’两个属性
当然了,我们还是需要自定义一组数据供ListView使用,这边就使用上面案例的数据
根据数据实例化ListView,参考上面案例,这里只粘贴Item部分,其它的就不重复了
视图部分

var ListViewDemo = React.createClass({
      getInitialState(){
          // 初始化数据源
          var ds = new ListView.DataSource({rowHasChanged:(r1, r2) => r1 != r2});
          return{
              dataSource : ds.cloneWithRows(newData)
          }
      },
      render(){
          return(
              <ListView
                  dataSource={this.state.dataSource}
                  renderRow={this.renderRow}
                  // 设置contentContainerStyle
                  contentContainerStyle={styles.contentViewStyle}
              />
          );
      },

      // 返回一个Item
      renderRow(rowData){
          return(
          {/* 实例化Item */}
          <View style={styles.itemStyle}>
              <Image source={{uri:rowData.img}} style={styles.itemImageStyle}/>
              <Text>{rowData.title}</Text>
          </View>
          );
      }
      var styles = StyleSheet.create({

      contentViewStyle: {
          // 主轴方向
          flexDirection:'row',
          // 换行
          flexWrap:'wrap'
          }

echat
首先通过socket将数据接收到客户端界面,然后将接收到的数据进行处理,设置两个数组集分别是次数集和距离集。然后
中的option

  const option = {
      xAxis: {
          data:datas2
      },
      yAxis: {},
      series: [{
          name: '入侵次数',
          type: 'bar',
          data: datas
      }]
    };

option里面有三个属性,分别是xAxis表示 x轴给予的数据是距离集,yAxis没有给与数据,series数组对象里面放置入侵次数集;这样就能将每个距离对应一个入侵次数。

RN组件的生命周期整理如下图:
在这里插入图片描述
组件的属性(props)和状态(state)
1.属性(props)
它是组件的不可变属性(组件自己不可以自己修改props)
组件自身定义了一组props作为对外提供的接口,展示一个组件时只需要指定props作为节点的属性。 一般组件很少需要对外公开方法,唯一的交互途径就是props。所以说它也是父组件与子组件通信的桥梁。
组件自己不可以自己修改props,只可由其他组件调用它时在外部修改。
2.状态(state)
它是组件的内部状态属性,主要用来存储组件自身需要的数据
除了初始化时可能由props来决定,之后就完全由组件自身去维护。
组件中由系统定义了setState方法,每次调用setState时都会更新组件的状态,触发render方法重新渲染界面。
需要注意的是render方法是被异步调用的,这可以保证同步的多个setState方法只会触发一次render,这样做是有利于提高性能的。
组件的生命周期
对于自定义组件,除了必须实现的render方法,还有一些其他的可选方法可被调用。这些方法会在组件的不同时期之行,所以也可以说这些方法是组件的生命周期方法。
注意:由于this.props和this.state都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props表示那些一旦定义,就不再改变的特性,而this.state是会随着用户互动而产生变化的特性。
1.constructor(props)
这里是对控件的一些状态进行初始化,由于该函数不同于defaultProps,在以后的过程中,会再次调用,所以可以将控制控件的状态的一些变量放在这里初始化,如控件上显示的文字,可以通过this.state来获取值,通过this.setState来修改state值。
2.componentWillMount()
准备加载组件
这个调用时机是在组件创建,并初始化了状态之后,在第一次绘制 render() 之前。可以在这里做一些业务初始化操作,也可以设置组件状态。这个函数在整个生命周期中只被调用一次。
如果在这个函数里面调用setState,本次的render函数可以看到更新后的state,并且只渲染一次。
3.render()
render是一个组件必须有的方法,形式为一个函数,渲染界面,并返回JSX或其他组件来构成DOM,和Andoid的XML布局、WPF的XAML布局类似,只能返回一个顶级元素。
4.componentDidMount()
在组件第一次绘制之后,会调用 componentDidMount(),通知组件已经加载完成。这个函数调用的时候,其虚拟 DOM 已经构建完成,你可以在这个函数开始获取其中的元素或者子组件了。需要注意的是,RN 框架是先调用子组件的 componentDidMount(),然后调用父组件的函数。从这个函数开始,就可以和 JS 其他框架交互了,例如设置计时 setTimeout 或者 setInterval,或者发起网络请求。这个函数也是只被调用一次。这个函数之后,就进入了稳定运行状态,等待事件触发。
5.componentWillReceiveProps(nextProps)
当组件接收到新的props时,会触发该函数。在该函数中,通常可以调用setState()来完成对stated的修改。
输入参数 nextProps 是即将被设置的属性,旧的属性还是可以通过 this.props 来获取。在这个回调函数里面,你可以根据属性的变化,通过调用 this.setState() 来更新你的组件状态,这里调用更新状态是安全的,并不会触发额外的 render() 调用。
6.shouldComponentUpdate(nextProps,nextState)
返回布尔值(决定是否需要更新组件)
输入参数 nextProps 和上面的 componentWillReceiveProps 函数一样,nextState 表示组件即将更新的状态值。这个函数的返回值决定是否需要更新组件,如果 true 表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。
默认情况下,这个函数永远返回 true 用来保证数据变化的时候 UI 能够同步更新。在大型项目中,你可以自己重载这个函数,通过检查变化前后属性和状态,来决定 UI 是否需要更新,能有效提高应用性能。
7.componentWillUpdate(nextProps,nextState)
shouldComponentUpdate返回true或者调用forceUpdate之后,就会开始准更新组件,并调用 componentWillUpdate()。
输入参数与 shouldComponentUpdate 一样,在这个回调中,可以做一些在更新界面之前要做的事情。需要特别注意的是,在这个函数里面,你就不能使用 this.setState 来修改状态。这个函数调用之后,就会把 nextProps 和 nextState 分别设置到 this.props 和 this.state 中。紧接着这个函数,就会调用 render() 来更新界面了。
8.componentDidUpdate( )
虚拟DOM同步到DOM中后,执行该方法,可以在这个方法中做DOM操作。
除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。
componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以对应起来。区别在于,前者只有在挂载的时候会被调用;而后者在以后的每次更新渲染之后都会被调用。
9.componentWillReceiveProps(nextProps)
当组件接收到新的props时,会触发该函数。在该函数中,通常可以调用setState()来完成对state的修改。
输入参数 nextProps 是即将被设置的属性,旧的属性还是可以通过 this.props 来获取。在这个回调函数里面,你可以根据属性的变化,通过调用 this.setState() 来更新你的组件状态,这里调用更新状态是安全的,并不会触发额外的 render() 调用。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值