React-native框架(一)

一、环境的配置工作:

1.安装Homebrew:ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.安装node和npm
3.安装watchman:brew install watchman
4.安装react native:npm install -g react-native-cli;有权限的问题,需要再命令行的开头加上sudo( sudo npm install -g react-native-cli)。
    4.1.选择目标路径:cd+"目标文件夹路径"
    4.2.初始化react-native:react-native init "项目工程的名称"

调试命令:
    刷新操作:commond+r
    iOS开发调试上面的菜单栏:commond+d

二、react-native的代码智能提醒

Mac下安装

  • 将ReactNative.xml复制~/Library/Preferences/WebStorm11/templates

  • 重启 WebStrom
  • 注意事项:因为安装的WebStrom的版本不一定一样,所以文件的路径WebStorm11不一致

    2.1 cd+文件路径,之后执行以下的指令:git clone https://github.com/virtoolswebplayer/ReactNative-LiveTemplate
    2.2 打开终端: 输入ls命令(查看文件的目录)
    
    React-native框架(一)_第1张图片
    屏幕快照 2016-09-18 下午1.22.23.png
    2.3 导入文件路径:cd ~/Library/Preferences/
    2.4 找到自己安装的WebStrom的版本:ls
    
    React-native框架(一)_第2张图片
    屏幕快照 2016-09-18 下午1.25.44.png
    2.5 导入自己安装 WebStorm2016.2的版本路径:cd WebStorm2016.2
    2.6 查看该路径下面的文件目录:ls
    2.7 注意这个命令之间有空格:cd ..
    2.8 打开这个文件:open WebStorm2016.2
    
    React-native框架(一)_第3张图片
    屏幕快照 2016-09-18 下午1.31.40.png
    2.9 将ReactNative.xml复制options文件夹下面即可;为了保证万无一失,在和options的文件夹下面建立一个同级的文件夹templates,里面也放一份ReactNative.xml
    2.10 重启WebStrom即可
    

    三、react-native的常见的组件和事件

    3.1 获取屏幕的分辨率、高度、宽度
    var Dimensions = requires('Dimensions');
    Dimensions.get('window').width;
    Dimensions.get('window').height;
    Dimensions.get('window').scale;
    
    var Dimensions = require('Dimensions');
    var screenWidth = Dimensions.get('window').width;
    
    var  Dimensions = require('Dimensions');
    var {width} = Dimensions.get('window');
    
    Cmd+R重新加载新代码的数据
    
    3.2 常见的一些错误
    React-native框架(一)_第4张图片
    屏幕快照 2016-09-12 下午2.19.29.png

    Raw text cannot be used outside of a tag. Not rendering string: 'keyboardType:'

    解决方法1:该引入的StyleSheet没有引入

    import {
      AppRegistry,
        StyleSheet,
        View,
        TextInput
    } from 'react-native';
    

    解决方法2:TextInput引入属性方式

    class helloword extends Component {
    render()
     {
        return (
          
           
    //以下方式error,应该是写道TextInput标签里面
          {/*placeholder="TextInput"*/}  
          {/*keyboardType:{"number-pad"}*/} 
         
      
    );
    

    }}

    3.3 常用的事件
    //EX5设置
    var DTouchabelDemo = React.createClass({
        getInitialState(){
            return{
                //初始的状态值
                title:'未操作' 
            }
        },
        render(){
            return(
          
              this.activeEvent('点击')} 
                               onPressIn={()=>this.activeEvent('按下')}  
                               onPressOut={()=>this.activeEvent('抬起')}
                               onLongPress={()=>this.activeEvent('长按')}>
                
                      按钮
                
              
              
                  //常见的事件的状态的标题
                  {this.state.title}
              
          
      )
    },
    //当点击按钮
        activeEvent(event){
            this.setState({
                title:event
            })
    }});
    
    3.4 React-native组件的生命周期
    React-native组件的生命周期分为三个阶段:实例化阶段、存在性阶段和销毁阶段。Mount  Update  Unmount
    1、实例化阶段的函数介绍:
    1)getDefaultProps()函数初始化一些默认的属性,将固定的内容放到这个函数里面的进行赋值和初始化,在组件中可以通过this.props拿到属性。⚠️不可改变
    2)getInitialState()函数对组件的初始状态赋值,状态值是可变的,通过this.state取出组件的状态值。⚠️使用this.state一定会调用render()方法,内部做些判断需要不需要进行重新渲染。
    3)componentWillMount()函数,相当于oc里面的viewWillAppear视图即将出现时候调用。
    4)render()函数,是一个组件里面必须要有,本质上是一个函数,并返回JSX和其他组件来组成DOM。⚠️在render函数里面,只能通过this.props和this.state来访问之前函数的一些数据。
    5)componentDidMount()函数,是在调用render函数之后调用的函数。在组件加载成功,并被成功的渲染出来,所要执行的一些后续的一些操作(比如网络请求和一些数据的处理)。
    

    3.5 获取真实的dom结点
    
    this.refs.oneView拿到view组件的dom结点属性
    

    四、组件的实战

    4.1 ScrollView组件学习
    //EX6
    class lianxi extends Component {
      render() {
        return ( 
           
                {this.renderChildView()}
           
       );
    }
     renderChildView(){
        var allchild = [];
        var colors = ['red','yellow','blue','green','purple'];
        for(var i = 0;i < 5;i++){
            allchild.push(
              
                {i}
              
          );
      }
      return allchild;
    }} 
    
    4.2 轮播图实现
    导入定时器大的类库:
    1)cd+项目的路径
    2)npm i react-timer-mixin --save
    

    轮播图的效果图:

    React-native框架(一)_第5张图片
    轮播图.gif

    轮播图完整代码实现:index.ios.js

    import React, { Component } from 'react';
    import {  
        AppRegistry,
        StyleSheet,
        Text,
        View,
        TouchableOpacity,
        ScrollView,
        Image,
        AlertIOS
    } from 'react-native';
    
    //注册计时器
    var TimerMixin = require('react-timer-mixin');
    //引入json数据
    var imageData = require('./ImageData.json');
    //计算屏幕的尺寸
    var  Dimensions = require('Dimensions');
    var {width} = Dimensions.get('window');
    
    var TimerDemo =React.createClass({
      //注册计时器
        mixins: [TimerMixin],
      //初始化函数,不可改变的值
        getDefaultProps(){
            return{
                duration:1000
            }
        },
      //初始化函数,可以改变的值
        getInitialState(){
            return{
                currenPage:0
            }
        },
    
        render(){
            return(
                
                    this.onAnimationEnd(e)}
                        //当开始拖拽的时候调用
                        onScrollBeginDrag = {this.onScrollBeginDrag}
                        //当开始拖拽的时候调用
                        onScrollEndDrag = {this.onScrollEndDrag}
                      >
                        {this.lbt()} 
                     
                {/*指示器*/}
                
                    {/*返回指示器的圆点*/} 
                   {this.indicateFunction()}
                
            
        )},
    
     //轮播图图片的设置函数
        lbt(){
            //image的数组
            var allImage = [];
            //数据数组
            var  imgsArr = imageData.data;
            for (var i = 0; i < imgsArr.length;i++){
                var model = imgsArr[i];
                allImage.push( 
                   
                ) 
           } 
         return allImage;
        },
    
    //圆点指示符返回函数
        indicateFunction(){
            var indicateArr = [];
            var style;
            for (var i = 0; i < imageData.data.length;i++){
               //三目运算符,注意不能放到这个数组的内部----自己犯的错误
                style = (i==this.state.currenPage) ? {color:'red'} : {color:'#ffffff'};
                indicateArr.push(
                    // 一定要加;
                    
                )
            } 
           return indicateArr;
        },
    
    //当每一帧滚动结束的时候调用函数
        onAnimationEnd(e){
            //水平方向的偏移量
             var offSet = e.nativeEvent.contentOffset.x;
            //计算当前的页数
            var currenPage = Math.floor(offSet / width);
            console.log(currenPage);
          //更新当前的状态机,重绘UI
            this.setState({
               currenPage:currenPage
            });
        },
    
    //页面加载完成之后调用的方法
        componentDidMount(){
            //开启定时器
            this.startTimer();
        },
    
    //加载完页面调用的方法函数
        startTimer(){
            //1.拿到scrollview
            var scrollview = this.refs.scrollView;
            var imageCount = imageData.data.length;
            //2.添加定时器
            this.timer = this.setInterval(function(){
            var activePage = 0;
            //越界处理:注意自己犯的错误this.state.currenPage写成this.state.currentPage,current单词写错
            if((this.state.currenPage+1) >= imageCount){
                activePage = 0;
                // AlertIOS.alert('越界处理');
            }else {
                activePage = this.state.currenPage+1;
            }
            //更新状态机
            this.setState({
                 currenPage:activePage
            });
            //让图片滚动起来
            var offsetPicture = activePage* width;
            scrollview.scrollResponderScrollTo({x:offsetPicture,y:0,animated:true});
            },this.props.duration)
        },
    
    //开始拖拽时调用
        onScrollBeginDrag(){
             this.clearInterval(this.timer);
          }, 
    //结束拖拽时调用
        onScrollEndDrag()    {
            this.startTimer();
        }
    
    });
    
    
    //样式设置
    const styles = StyleSheet.create({
    container:{
        marginTop:30
    },
    indicatePageStyle:{
        width:width,
        height:25,
        backgroundColor:'rgba(0,0,0,0.3)',
        position:'absolute',
        bottom:0,
        // 确定主轴的方向
        flexDirection:'row', 
       //侧轴居中显示,alignItems不是alignItem
        alignItems:'center'
        },
    });
    
      AppRegistry.registerComponent('lianxi', () => TimerDemo);
    

    遇到的问题:
    1.这边是从json文件中拿到的数据,将image的图片的信息放到xcode的工程里面,将json文件放到webstorm工程里面;
    2.低级错误❌
        1-1问题:Can't find variable: Image; 
        处理方法:因为Image的组件没有引入到工程里面;
     3.错误
       因为判断条件的字母拼写错误,导致这个条件一直不走,⚠️.(this.state.currenPage写成this.state.currentPage,current单词写错)
    
    4.3 ListView基本方式实战

    1.ListView相当于oc里面的tableView,添加了点击事件, 效果图如下:

    React-native框架(一)_第6张图片
    listview.gif

    2.代码展示

    //导入json数据
    var Wine = require('./Wine.json');
    //获取屏幕的尺寸
    var Dimensions = require('Dimensions');
    var {width} = Dimensions.get('window');
    var GListViewDemo = React.createClass({
        // 设置初始值
        getInitialState(){ 
           // 1.1 设置数据源
            var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
            // 1.2 设置返回数据
            return{ 
         // cloneWithRows 放置数组   
               dataSource: ds.cloneWithRows(Wine) 
         }},
    
        // 设置render函数
        render(){
           return( 
               
             );
          },
    
        //逐条解析数据函数
        renderRow(rowData,sectionID,rowID,highlightRow){
            //逐条解析数据:注意的是这个模型的数据必须发要返回出来
            return(
                 {AlertIOS.alert('第'+rowID+'行')}}>
                    
                     {/*左边的图片*/}
                       
                     {/*右边的文字*/}
                      
                          {rowData.name}                
                          ${rowData.money} 
                      
                  
                
          )}
    });
    
    //样式的设置
    const styles = StyleSheet.create({
      modelStyle:{
        marginTop:10,
        width:width,
        height:100,
        // 下划线
        borderBottomWidth:1.5,
        borderBottomColor:'#e8e8e8',
        // 确定主轴的方向
        flexDirection:'row'
      }, 
     imgStyle:{
        marginTop:20,
        width: 60,
        height:60
      }, 
     rightTextStyle:{
        marginLeft:20,
        // 主轴的对齐方式
        justifyContent:'center'
      },
      topTextStyle:{
        width:0.7*width
      },
      bottomTextStyle:{
        fontSize:15,
        marginTop:30
      }
    });
    

    遇到的问题:1)render函数里面的return(),而不是return{}
              2)renderRow函数必须要把cell的模型的控件返回出来
              3)下划线的设置:borderBottomWidth和borderBottomColor
    
    4.4 ListView九宫格实战

    效果图:

    React-native框架(一)_第7张图片
    屏幕快照 2016-09-24 下午4.21.54.png

    代码:

    // 导入json数据
    var share = require('./shareData.json');
    //获取屏幕的尺寸
    var Dimensions = require('Dimensions');
    var {width} = Dimensions.get('window');
    var  count = 3;
    var cellWidth = 100;
    var marginX = (width-count*cellWidth) / (count+1);
    var GListViewDemo = React.createClass({
        // 设置初始值
        getInitialState(){
            // 1.1 设置数据源
            var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
            // 1.2 设置返回数据
            return{
                dataSource: ds.cloneWithRows(share.data)  // cloneWithRows 放置数组
            }
        },
    
        // 设置render函数:利用jsx语法对页面进行渲染
        render(){
            return(
                
                
            );
        },
    
        //cell模型UI布局:逐条解析数据:注意的是这个模型的数据必须发要返回出来
        renderRow(rowData){ 
            return(
                {AlertIOS.alert('hh')}}>
                  
                      
                      {rowData.title}
                  
              
           )}
    });
    
        //样式设置
        const styles = StyleSheet.create({ 
           listViewStyle:{ 
               //设置横向布局
                flexDirection:'row',
                //设置换行显示
                flexWrap:'wrap', 
             height:100
            },
            cellBackStyle:{ 
               width:cellWidth,
                height:cellWidth,
                marginLeft:marginX, 
               marginTop:30, 
               alignItems:'center'//居中显示
            }
        });
    

    遇到的问题:

    React-native框架(一)_第8张图片
    图1
    React-native框架(一)_第9张图片
    图2
    React-native框架(一)_第10张图片
    图3
    1.图1问题是因为没有设置换行属性:flexWrap:'wrap'
    2.图2问题:设置了整体的布局方向和换行属性之后还是不行;解决:removeClippedSubviews={false},当超出画面以外的子视图,这个属性默认是true隐藏,即子视图不会出现到父视图上面(不会出现)。
    3.图3问题:一行的cell占了超过自身的高度,设置一下listview高度即可(⚠️设置的是listViewStyle的样式中设置height属性)。
    
    4.5 ListView分组实战

    效果图:

    React-native框架(一)_第11张图片
    图1
    React-native框架(一)_第12张图片
    图2

    代码:

    // 导入json数据
    var cars = require('./Car.json');
    var ListViewDemo3 = React.createClass({
    
        //初始化函数
     getInitialState(){
        var getSectionData = (dataBlob,sectionID) =>{ 
           return dataBlob[sectionID]; 
         };
        var getRowData = (dataBlob,sectionID,rowID) =>{
            return dataBlob[sectionID+':'+rowID];
        };
        return{ 
           dataSource:new ListView.DataSource({
                getSectionData:getSectionData, 
                getRowData:getRowData, 
               rowHasChanged:(r1,r2) => r1 !== r2,
                sectionHeaderHasChanged:(s1,s2)  => s1 !== s2
            })
        }},
    
    
        //页面加载完之后调用的方法
        componentDidMount(){
            this.jsonDataFunction();
        },
    
        //数据加载处理函数
        jsonDataFunction(){
            //json的所有数据
            var jsonArray = cars.data;
            //定义变量存放区标号,行标号,区标题,所有的汽车的品牌信息
            var sectionIDs = [], 
                rowIDs = [],
                dataBlob = {},
                carsArray = [];
            for(var i = 0; i < jsonArray.length;i ++){
                  //区号
                  sectionIDs.push(i);
                  //区标题
                  dataBlob[i] = jsonArray[i].title;
                  //所有的汽车的品牌信息
                  carsArray = jsonArray[i].cars;
                  //相当于声明一个二维数组,⚠️这句 
                  rowIDs[i] = [];
                 for(var j = 0; j < carsArray.length; j++){
                      rowIDs[i].push(j);
                    //把每一行的汽车信息放入到数组中
                    dataBlob[i + ':' + j] = carsArray[j];
                }
              }
    
        //更新状态机:⚠️更新状态的函数为setState,而不是state 
           this.setState({
                 dataSource:this.state.dataSource.cloneWithRowsAndSections(dataBlob,sectionIDs,rowIDs)
            });
      },
    
    //数据UI的喧染
     render(){
        return( 
           
                {/*头部的标题样式*/}
                
                    cjw之分组listView学习
                
                {/*listView数据*/}
                
            
        );
    },
    
    
    //每一行数据解析布局
     renderRow(rowData){
        return( 
           AlertIOS.alert('r')}>
                
                    
                    {rowData.name}
                
            
      )},
    
    //区标题的数据布局
    renderSectionHeader(sectionData,sectionID){
        return(
            AlertIOS.alert('h')}>
                
                    {sectionData}
                
            
        );
    }
    
    
    //样式布局设置
    const styles = StyleSheet.create({
        pageStyle:{
            flex:1
        },
        titlePageStyle:{
            height:60,
            alignItems:'center',
            padding:20
        },
        textPageStyle:{
          fontSize:18
        },
        rowListViewPageStyle:{
            flexDirection:'row'
        },
        rowImageStyle:{
            width:60,
            height:60
        },
        rowTextStyle:{
            padding:20
        },
        headerViewStyle:{
            height:40,
            backgroundColor:'orange',
            justifyContent:'center'
        },
        headerTextStyle:{
            fontSize:18
        }
    });
    

    知识点补充和遇到的问题

    1)知识点补充
    //设置主轴的方向
    flexDirection:'row'
    //侧轴方向居中
     alignItems:'center'
     //主轴方向居中
    justifyContent:'center'
    2)遇到的问题
        2-1//dataSource:this.state.dataSource这一种写的方式会导致语法报错
        //正确的写法:
        dataSource={this.state.dataSource}
    
        2-2布局完成之后设置的listView的视图,并不能滚动起来
        解决方法:最外面的view视图里面设置一个布满全屏的属性flex:1

    你可能感兴趣的:(React-native框架(一))