React-native框架(一)

一、環(huán)境的配置工作:

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;有權(quán)限的問題,需要再命令行的開頭加上sudo( sudo npm install -g react-native-cli)。
    4.1.選擇目標路徑:cd+"目標文件夾路徑"
    4.2.初始化react-native:react-native init "項目工程的名稱"

調(diào)試命令:
    刷新操作:commond+r
    iOS開發(fā)調(diào)試上面的菜單欄:commond+d

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

Mac下安裝
<li>將ReactNative.xml復制~/Library/Preferences/WebStorm11/templates</li>
<li>重啟 WebStrom</li>

注意事項:因為安裝的WebStrom的版本不一定一樣,所以文件的路徑WebStorm11不一致

2.1 cd+文件路徑,之后執(zhí)行以下的指令:git clone https://github.com/virtoolswebplayer/ReactNative-LiveTemplate
2.2 打開終端: 輸入ls命令(查看文件的目錄)
屏幕快照 2016-09-18 下午1.22.23.png
2.3 導入文件路徑:cd ~/Library/Preferences/
2.4 找到自己安裝的WebStrom的版本:ls
屏幕快照 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
屏幕快照 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重新加載新代碼的數(shù)據(jù)
3.2 常見的一些錯誤
屏幕快照 2016-09-12 下午2.19.29.png

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

解決方法1:該引入的StyleSheet沒有引入

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

解決方法2:TextInput引入屬性方式

class helloword extends Component {
render()
 {
    return (
      <View style={styles.container}>
      <TextInput style={styles.inputStyle} placeholder="TextInput" keyboardType='number-pad' clearButtonMode="while-editing"> 
//以下方式error,應該是寫道TextInput標簽里面
      {/*placeholder="TextInput"*/}  
      {/*keyboardType:{"number-pad"}*/} 
     </TextInput>
  </View>
);

}}

3.3 常用的事件
//EX5設置
var DTouchabelDemo = React.createClass({
    getInitialState(){
        return{
            //初始的狀態(tài)值
            title:'未操作' 
        }
    },
    render(){
        return(
      <View style={styles.container}>
          <TouchableOpacity activeOpacity={0.5} 
                           onPress={()=>this.activeEvent('點擊')} 
                           onPressIn={()=>this.activeEvent('按下')}  
                           onPressOut={()=>this.activeEvent('抬起')}
                           onLongPress={()=>this.activeEvent('長按')}>
            <View style={styles.textStyle}>
                  <Text>按鈕</Text>
            </View>
          </TouchableOpacity>
          <View>
              //常見的事件的狀態(tài)的標題
              <Text>{this.state.title}</Text>
          </View>
      </View>
  )
},
//當點擊按鈕
    activeEvent(event){
        this.setState({
            title:event
        })
}});
3.4 React-native組件的生命周期
React-native組件的生命周期分為三個階段:實例化階段、存在性階段和銷毀階段。Mount  Update  Unmount
1、實例化階段的函數(shù)介紹:
1)getDefaultProps()函數(shù)初始化一些默認的屬性,將固定的內(nèi)容放到這個函數(shù)里面的進行賦值和初始化,在組件中可以通過this.props拿到屬性。??不可改變
2)getInitialState()函數(shù)對組件的初始狀態(tài)賦值,狀態(tài)值是可變的,通過this.state取出組件的狀態(tài)值。??使用this.state一定會調(diào)用render()方法,內(nèi)部做些判斷需要不需要進行重新渲染。
3)componentWillMount()函數(shù),相當于oc里面的viewWillAppear視圖即將出現(xiàn)時候調(diào)用。
4)render()函數(shù),是一個組件里面必須要有,本質(zhì)上是一個函數(shù),并返回JSX和其他組件來組成DOM。??在render函數(shù)里面,只能通過this.props和this.state來訪問之前函數(shù)的一些數(shù)據(jù)。
5)componentDidMount()函數(shù),是在調(diào)用render函數(shù)之后調(diào)用的函數(shù)。在組件加載成功,并被成功的渲染出來,所要執(zhí)行的一些后續(xù)的一些操作(比如網(wǎng)絡請求和一些數(shù)據(jù)的處理)。

3.5 獲取真實的dom結(jié)點
<View ref="oneView"></View>
this.refs.oneView拿到view組件的dom結(jié)點屬性

四、組件的實戰(zhàn)

4.1 ScrollView組件學習
//EX6
class lianxi extends Component {
  render() {
    return ( 
       <ScrollView horizontal={true}        pagingEnabled={true}>
            {this.renderChildView()}
       </ScrollView>
   );
}
 renderChildView(){
    var allchild = [];
    var colors = ['red','yellow','blue','green','purple'];
    for(var i = 0;i < 5;i++){
        allchild.push(
          <View key={i} style={{backgroundColor:colors[i],width:414,height:200}}>
            <Text>{i}</Text>
          </View>
      );
  }
  return allchild;
}} 
4.2 輪播圖實現(xiàn)
導入定時器大的類庫:
1)cd+項目的路徑
2)npm i react-timer-mixin --save

輪播圖的效果圖:

輪播圖.gif

輪播圖完整代碼實現(xiàn):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數(shù)據(jù)
var imageData = require('./ImageData.json');
//計算屏幕的尺寸
var  Dimensions = require('Dimensions');
var {width} = Dimensions.get('window');

var TimerDemo =React.createClass({
  //注冊計時器
    mixins: [TimerMixin],
  //初始化函數(shù),不可改變的值
    getDefaultProps(){
        return{
            duration:1000
        }
    },
  //初始化函數(shù),可以改變的值
    getInitialState(){
        return{
            currenPage:0
        }
    },

    render(){
        return(
            <View style={styles.container}>
                <ScrollView ref="scrollView" 
                         horizontal={true}
                         showsHorizontalScrollIndicator={false}
                        pagingEnabled={true} 
                       //onMomentumScrollEnd={this.onAnimationEnd},不用加()代表會自動把ScrollView這個參數(shù)傳過去
                    //當一幀結(jié)束的時候調(diào)用
                    onMomentumScrollEnd={(e)=>this.onAnimationEnd(e)}
                    //當開始拖拽的時候調(diào)用
                    onScrollBeginDrag = {this.onScrollBeginDrag}
                    //當開始拖拽的時候調(diào)用
                    onScrollEndDrag = {this.onScrollEndDrag}
                  >
                    {this.lbt()} 
                 </ScrollView>
            {/*指示器*/}
            <View style={styles.indicatePageStyle}>
                {/*返回指示器的圓點*/} 
               {this.indicateFunction()}
            </View>
        </View>
    )},

 //輪播圖圖片的設置函數(shù)
    lbt(){
        //image的數(shù)組
        var allImage = [];
        //數(shù)據(jù)數(shù)組
        var  imgsArr = imageData.data;
        for (var i = 0; i < imgsArr.length;i++){
            var model = imgsArr[i];
            allImage.push( 
               <Image key={i} source={{uri:model.img}} style={{width: width, height: 200}}/>
            ) 
       } 
     return allImage;
    },

//圓點指示符返回函數(shù)
    indicateFunction(){
        var indicateArr = [];
        var style;
        for (var i = 0; i < imageData.data.length;i++){
           //三目運算符,注意不能放到這個數(shù)組的內(nèi)部----自己犯的錯誤
            style = (i==this.state.currenPage) ? {color:'red'} : {color:'#ffffff'};
            indicateArr.push(
                // 一定要加;
                <Text key={i} style={[{fontSize:25}, style]}>?</Text>
            )
        } 
       return indicateArr;
    },

//當每一幀滾動結(jié)束的時候調(diào)用函數(shù)
    onAnimationEnd(e){
        //水平方向的偏移量
         var offSet = e.nativeEvent.contentOffset.x;
        //計算當前的頁數(shù)
        var currenPage = Math.floor(offSet / width);
        console.log(currenPage);
      //更新當前的狀態(tài)機,重繪UI
        this.setState({
           currenPage:currenPage
        });
    },

//頁面加載完成之后調(diào)用的方法
    componentDidMount(){
        //開啟定時器
        this.startTimer();
    },

//加載完頁面調(diào)用的方法函數(shù)
    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;
        }
        //更新狀態(tài)機
        this.setState({
             currenPage:activePage
        });
        //讓圖片滾動起來
        var offsetPicture = activePage* width;
        scrollview.scrollResponderScrollTo({x:offsetPicture,y:0,animated:true});
        },this.props.duration)
    },

//開始拖拽時調(diào)用
    onScrollBeginDrag(){
         this.clearInterval(this.timer);
      }, 
//結(jié)束拖拽時調(diào)用
    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', 
   //側(cè)軸居中顯示,alignItems不是alignItem
    alignItems:'center'
    },
});

  AppRegistry.registerComponent('lianxi', () => TimerDemo);

遇到的問題:
1.這邊是從json文件中拿到的數(shù)據(jù),將image的圖片的信息放到xcode的工程里面,將json文件放到webstorm工程里面;
2.低級錯誤?
    1-1問題:Can't find variable: Image; 
    處理方法:因為Image的組件沒有引入到工程里面;
 3.錯誤
   因為判斷條件的字母拼寫錯誤,導致這個條件一直不走,??.(this.state.currenPage寫成this.state.currentPage,current單詞寫錯)
4.3 ListView基本方式實戰(zhàn)

1.ListView相當于oc里面的tableView,添加了點擊事件, 效果圖如下:

listview.gif

2.代碼展示

//導入json數(shù)據(jù)
var Wine = require('./Wine.json');
//獲取屏幕的尺寸
var Dimensions = require('Dimensions');
var {width} = Dimensions.get('window');
var GListViewDemo = React.createClass({
    // 設置初始值
    getInitialState(){ 
       // 1.1 設置數(shù)據(jù)源
        var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
        // 1.2 設置返回數(shù)據(jù)
        return{ 
     // cloneWithRows 放置數(shù)組   
           dataSource: ds.cloneWithRows(Wine) 
     }},

    // 設置render函數(shù)
    render(){
       return( 
           <ListView
              // 數(shù)據(jù)源
                dataSource={this.state.dataSource}  
                renderRow={this.renderRow} 
           />
         );
      },

    //逐條解析數(shù)據(jù)函數(shù)
    renderRow(rowData,sectionID,rowID,highlightRow){
        //逐條解析數(shù)據(jù):注意的是這個模型的數(shù)據(jù)必須發(fā)要返回出來
        return(
            <TouchableOpacity activeOpacity={0.3} onPress={() => {AlertIOS.alert('第'+rowID+'行')}}>
               <View style={styles.modelStyle}> 
                 {/*左邊的圖片*/}
                  <Image style={styles.imgStyle} source={{uri:rowData.image}}/> 
                 {/*右邊的文字*/}
                  <View style={styles.rightTextStyle}>
                      <Text style={styles.topTextStyle}>{rowData.name}</Text>                
                      <Text style={styles.bottomTextStyle}>${rowData.money} </Text>
                  </View>
              </View>
            </TouchableOpacity>
      )}
});

//樣式的設置
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函數(shù)里面的return(),而不是return{}
          2)renderRow函數(shù)必須要把cell的模型的控件返回出來
          3)下劃線的設置:borderBottomWidth和borderBottomColor
4.4 ListView九宮格實戰(zhàn)

效果圖:

屏幕快照 2016-09-24 下午4.21.54.png

代碼:

// 導入json數(shù)據(jù)
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 設置數(shù)據(jù)源
        var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
        // 1.2 設置返回數(shù)據(jù)
        return{
            dataSource: ds.cloneWithRows(share.data)  // cloneWithRows 放置數(shù)組
        }
    },

    // 設置render函數(shù):利用jsx語法對頁面進行渲染
    render(){
        return(
            <ListView            
                 dataSource={this.state.dataSource}  // 數(shù)據(jù)源
                 renderRow={this.renderRow}
                 contentContainerStyle={styles.listViewStyle}
                  //??要加上這行代碼,才會自動換行布局      
                 removeClippedSubviews={false}
             >
            </ListView>
        );
    },

    //cell模型UI布局:逐條解析數(shù)據(jù):注意的是這個模型的數(shù)據(jù)必須發(fā)要返回出來
    renderRow(rowData){ 
        return(
           <TouchableOpacity activeOpacity={0.5} onPress={() => {AlertIOS.alert('hh')}}>
              <View style={styles.cellBackStyle}>
                  <Image source={{uri: rowData.icon}} style={{width:80,                height:80}} />
                  <Text>{rowData.title}</Text>
              </View>
          </TouchableOpacity>
       )}
});

    //樣式設置
    const styles = StyleSheet.create({ 
       listViewStyle:{ 
           //設置橫向布局
            flexDirection:'row',
            //設置換行顯示
            flexWrap:'wrap', 
         height:100
        },
        cellBackStyle:{ 
           width:cellWidth,
            height:cellWidth,
            marginLeft:marginX, 
           marginTop:30, 
           alignItems:'center'//居中顯示
        }
    });

遇到的問題:

圖1
圖2
圖3
1.圖1問題是因為沒有設置換行屬性:flexWrap:'wrap'
2.圖2問題:設置了整體的布局方向和換行屬性之后還是不行;解決:removeClippedSubviews={false},當超出畫面以外的子視圖,這個屬性默認是true隱藏,即子視圖不會出現(xiàn)到父視圖上面(不會出現(xiàn))。
3.圖3問題:一行的cell占了超過自身的高度,設置一下listview高度即可(??設置的是listViewStyle的樣式中設置height屬性)。
4.5 ListView分組實戰(zhàn)

效果圖:

圖1
圖2

代碼:

// 導入json數(shù)據(jù)
var cars = require('./Car.json');
var ListViewDemo3 = React.createClass({

    //初始化函數(shù)
 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
        })
    }},


    //頁面加載完之后調(diào)用的方法
    componentDidMount(){
        this.jsonDataFunction();
    },

    //數(shù)據(jù)加載處理函數(shù)
    jsonDataFunction(){
        //json的所有數(shù)據(jù)
        var jsonArray = cars.data;
        //定義變量存放區(qū)標號,行標號,區(qū)標題,所有的汽車的品牌信息
        var sectionIDs = [], 
            rowIDs = [],
            dataBlob = {},
            carsArray = [];
        for(var i = 0; i < jsonArray.length;i ++){
              //區(qū)號
              sectionIDs.push(i);
              //區(qū)標題
              dataBlob[i] = jsonArray[i].title;
              //所有的汽車的品牌信息
              carsArray = jsonArray[i].cars;
              //相當于聲明一個二維數(shù)組,??這句 
              rowIDs[i] = [];
             for(var j = 0; j < carsArray.length; j++){
                  rowIDs[i].push(j);
                //把每一行的汽車信息放入到數(shù)組中
                dataBlob[i + ':' + j] = carsArray[j];
            }
          }

    //更新狀態(tài)機:??更新狀態(tài)的函數(shù)為setState,而不是state 
       this.setState({
             dataSource:this.state.dataSource.cloneWithRowsAndSections(dataBlob,sectionIDs,rowIDs)
        });
  },

//數(shù)據(jù)UI的喧染
 render(){
    return( 
       <View style={styles.pageStyle}>
            {/*頭部的標題樣式*/}
            <View style={styles.titlePageStyle}>
                <Text style={styles.textPageStyle}>cjw之分組listView學習</Text>
            </View>
            {/*listView數(shù)據(jù)*/}
            <ListView
                //dataSource:this.state.dataSource這一種寫的方式會導致語法報錯
                dataSource={this.state.dataSource}
                renderRow={this.renderRow}
                renderSectionHeader={this.renderSectionHeader}
            />
        </View>
    );
},


//每一行數(shù)據(jù)解析布局
 renderRow(rowData){
    return( 
       <TouchableOpacity activeOpacity={0.5} onPress={()=>AlertIOS.alert('r')}>
            <View style={styles.rowListViewPageStyle}>
                <Image source={{uri:rowData.icon}} style={styles.rowImageStyle}/>
                <Text style={styles.rowTextStyle}>{rowData.name}</Text>
            </View>
        </TouchableOpacity>
  )},

//區(qū)標題的數(shù)據(jù)布局
renderSectionHeader(sectionData,sectionID){
    return(
        <TouchableOpacity activeOpacity={0.5} onPress={()=>AlertIOS.alert('h')}>
            <View style={styles.headerViewStyle}>
                <Text style={styles.headerTextStyle}>{sectionData}</Text>
            </View>
        </TouchableOpacity>
    );
}


//樣式布局設置
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'
//側(cè)軸方向居中
 alignItems:'center'
 //主軸方向居中
justifyContent:'center'
2)遇到的問題
    2-1//dataSource:this.state.dataSource這一種寫的方式會導致語法報錯
    //正確的寫法:
    dataSource={this.state.dataSource}

    2-2布局完成之后設置的listView的視圖,并不能滾動起來
    解決方法:最外面的view視圖里面設置一個布滿全屏的屬性flex:1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容