1. 程式人生 > >RN上拉重新整理下拉載入

RN上拉重新整理下拉載入

第一步:安裝NodeJS10,Python2.7,JDK8,配置jdk,python環境變數 設定npm映象: npm config set registry https://registry.npm.taobao.org –global npm config set disturl https://npm.taobao.org/dist –global 第二步:Yarn、React Native的命令列工具(react-native-cli) npm install -g yarn react-native-cli 安裝完yarn後同理也要設定映象源: yarn config set registry

https://registry.npm.taobao.org –global yarn config set disturl https://npm.taobao.org/dist –global 第三步:android studio 安裝as,選擇custom,勾選intel HAXM 安裝完成後,在Android Studio的歡迎介面中選擇Configure | SDK Manager。 在SDK Platforms視窗中,選擇Show Package Details,然後在Android 6.0 (Marshmallow)中勾選Google APIs、Android SDK Platform 23、Intel x86 Atom System Image、Intel x86 Atom_64 System Image以及Google APIs Intel x86 Atom_64 System Image。 在SDK Tools視窗中,選擇Show Package Details,然後在Android SDK Build Tools中勾選Android SDK Build-Tools 23.0.1 第四步:設定ANDROID_HOME環境變數和adb環境變數 第五步: 安裝Genymotion,設定adb 第六步: 測試安裝 react-native init HelloWorld –version 0.55.4 && cd HelloWorld react-native init Gone –version 0.55.4 && cd Gone

下載依賴 首先是在你的應用中安裝此庫: yarn add react-navigation

yarn add react-native-vector-icons * react-native link npm install –save react-native-refresh-list-view 自動載入

Yarn add react-native-render-html

一、RN搭建開發環境 1.安裝依賴軟體: Node.js 8.3以上 D:\Program Files\nodejs\

    Python       2.x以上     
        D:\Python27\         
        D:\Python27\Scripts
    JDK          1.8          
        Java_Home=C:\Program Files\Java\jdk1.8.0_65       
        %Java_Home%\bin
    Android SDK              
        ANDROID_HOME=D:\AndroidStudio\SDK
        %ANDROID_HOME%\platform-tools
        %ANDROID_HOME%\tools

2.Yarn、React Native的命令列工具

    Yarn與npm都是軟體管理工具,Yarn速度快很多

    npm(該命令是node.js中的命令,用於安裝軟體)

    設定npm映象:
        npm config set registry https://registry.npm.taobao.org --global 
        npm config set disturl https://npm.taobao.org/dist --global

    Yarn、React Native的命令列工具(react-native-cli)
        npm install -g yarn react-native-cli

    安裝完yarn後同理也要設定映象源:
        yarn config set registry https://registry.npm.taobao.org --global 
        yarn config set disturl https://npm.taobao.org/dist --global4

    測試:
        react-native --version    
        yarn -v

3.環境使用
        React開發環境:VScode
            Node.js      8.3以上 

        Android環境(編譯執行環境):AS
            SDK platform:開發版本庫
                Android SDK Platform 26    (0.56)    
                Android SDK Platform 23    (0.55.4)

                Google Api Intel x86 Atom_64 System Image   ;   intel HAXM   (建立虛擬機器使用)

            SDK bulid tools:程式碼編譯工具
                26.0.3                     (0.56) 
                23.0.1                     (0.55.4)


4.建立專案執行到模擬器:
    方式一:
        1.建立專案
            react-native init HelloWorld
            react-native init HelloWorld --version 0.55.4  
        2.進入到專案目錄中
            cd HelloWorld     目錄cmd
        3.執行
            react-native run-android

    方式二:
        1.匯入新專案
            使用其他可用專案即可
        2.進入到專案目錄中
            cd HelloWorld     目錄cmd
        3.執行
            react-native run-android

    方式三:
        Android Studio開啟android專案,編譯執行,到模擬器
            模擬器配置設定:
                搖一搖:啟動設定頁面      Ctrl+M
                HOST:配置服務連線地址:   11.11.11.11:8081

        開啟node服務:
            npm start開啟

    方式四:
        直接使用.apk檔案轉入模擬器
            模擬器配置設定:
                    搖一搖:啟動設定頁面      Ctrl+M
                    HOST:配置服務連線地址:   11.11.11.11:8081
        開啟node服務:
                npm start開啟


5.RN常用命令:
    react-natice init HelloWorld
    react-native init HelloWorld --version 0.55.4  
    react-native --version
    react-native run-android
    react-narive run-ios   

    npm install -g yarn react-native-cli    安裝軟體
    npm start                               開啟Node服務

二、RN專案結構: android 編譯執行程式碼

ios          編譯執行程式碼

node_modules  自動生成三方依賴庫

App.js     顯示的元件頁面

index.js  渲染顯示頁面

    AppRegistry.registerComponent('HelloWorld', () => App);
        將APP元件渲染到Android獲取IOS中"HelloWorld"標記

    Android渲染路徑:
        @Override
        protected String getJSMainModuleName() {
            return "index";
        }

        @Override
        protected String getMainComponentName() {
            return "HelloWorld";
        }

    IOS渲染路徑:
        jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

        RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                    moduleName:@"HelloWorld"
                                                    initialProperties:nil
                                                    launchOptions:launchOptions];
package.json   系統專案配置檔案

三、頁面元件分析 index.js 渲染顯示頁面 匯入依賴:react-native import { AppRegistry } from ‘react-native’; import App from ‘./App’;

    渲染:將App元件替換HelloWorld標記
    AppRegistry.registerComponent('HelloWorld', () => App);

App.js    顯示的元件頁面

    匯入依賴:react(自定義元件類)   react-native(使用RN中的控制元件和API)  
    import React, { Component } from "react";
    import { StyleSheet, Text, View } from "react-native";


    定義元件
    class App extends Component {

        render() {
            return (

            //渲染頁面:RN中控制元件使用
            <View style={styles.container}>
                <Text style={styles.welcome}>Welcome to React Native!</Text>
                <Text style={styles.instructions}>To get started, edit App.js</Text>
                <Text style={styles.instructions}>歡迎來到LOL</Text>
            </View>
            );
        }
    }

    //建立樣式使用
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            justifyContent: "center",
            alignItems: "center",
            backgroundColor: "#F5FCFF"
        },
        welcome: {
            fontSize: 20,
            textAlign: "center",
            margin: 10
        },
        instructions: {
            textAlign: "center",
            color: "#333333",
            marginBottom: 5
        }
    });


    //匯出元件
     export default App;

四、基本控制元件以及佈局樣式 View View是一個支援Flexbox佈局、樣式、一些觸控處理、和一些無障礙功能的容器, 並且它可以放到其它的視圖裡,也可以有任意多個任意型別的子檢視

<View style={{flexDirection: 'row', height: 100, padding: 20}}> 
    <View style={{backgroundColor: 'blue', flex: 0.3}} /> 
    <View style={{backgroundColor: 'red', flex: 0.5}} /> 
</View>

Text 顯示文字的React元件,並且它也支援巢狀、樣式,以及觸控處理

<Text style={styles.titleText} onPress={this.onPressTitle}> {this.state.titleText} </Text>

Image: 不同型別圖片的React元件,包括網路圖片、本地資源

<Image style={styles.icon} source={require('./icon.png')} />   同級
<Image style={styles.icon} source={require('./img/icon.png')} />   下級
<Image style={styles.icon} source={require('./../icon.png')} />   上級
<Image style={styles.icon} source={require('./../img/icon.png')} />  同級資料夾

<Image style={styles.logo} source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}} />

TextInput 輸入文字的基礎元件。 onChangeText的屬性,此屬性接受一個函式,而此函式會在文字變化時被呼叫。 onSubmitEditing的屬性,會在文字被提交後(使用者按下軟鍵盤上的提交鍵)呼叫

<TextInput 
    style={{height: 40}} 
    placeholder="Type here to translate!" 
    onChangeText={(text) => this.setState({text})} />
<Text 
style={{padding: 10, fontSize: 42}}> 
    {this.state.text}
</Text>

Button: 顯示一個簡單的按鈕 是一個簡單的跨平臺的按鈕元件。

<Button
    onPress={() => {
        Alert.alert("你點選了按鈕!");
    }}
    title="點我!"
    color="#841584"
/>

Touchable系列元件: TouchableHighlight來製作按鈕或者連結。注意此元件的背景會在使用者手指按下時變暗。

在Android 上還可以使用TouchableNativeFeedback,它會在使用者手指按下時形成類似墨水漣漪的視覺效果。

TouchableOpacity會在使用者手指按下時降低按鈕的透明度,而不會改變背景的顏色。

如果你想在處理點選事件的同時不顯示任何視覺反饋,則需要使用TouchableWithoutFeedback。

<TouchableHighlight
    onPress={this._onPressButton} //點選響應
    onLongPress={this._onLongPressButton} //長按響應
    underlayColor="white"
>
    <View style={styles.button}>
        <Text style={styles.buttonText}>TouchableHighlight</Text>
    </View>
</TouchableHighlight> 

//————————————————————————————————– 樣式: style的屬性;駝峰命名法,例如將background-color改為backgroundColor

還可以傳入一個數組——在陣列中位置居後的樣式物件比居前的優先順序更高,間接實現樣式的繼承

使用StyleSheet.create來集中定義元件的樣式

<View>
    <Text style={styles.red}>just red</Text> 
    <Text style={styles.bigblue}>just bigblue</Text> 
    <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text> 
    <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
</View>
const styles = StyleSheet.create({ 
    bigblue: { color: 'blue', fontWeight: 'bold', fontSize: 30, }, 
    red: { color: 'red', },
});

關於樣式
(1)普通內聯樣式:{{}},第一層{}是表示式,第二層{}是js物件;
                  <View style={{fontSize:40, width:80,}}> </View>
(2)呼叫樣式表:{樣式類.屬性}
                  <View style={styles.container}></View>
(3)樣式表和內聯樣式共存:{[]}
                  <View style={[styles.container, {fontSize:40, width:80}]}>
(4)多個樣式表:{[樣式類1, 樣式類2]}
                  <View style={[styles.container, styles.color]}>

彈性佈局Flexbox Flex佈局主要思想是:讓容器有能力讓其子專案能夠改變其寬度、高度(甚至是順序),以最佳方式填充可用空間

容器預設存在兩根軸:水平的主軸(main axis)和垂直的交叉軸;預設值是豎直軸(column)方向

在React Native中,有4個容器屬性,2個專案屬性,分別是:
    容器屬性:flexDirection   flexWrap   justifyContent  alignItems
    專案屬性:flex  alignSelf

flexDirection容器屬性: `row | row-reverse | column | column-reverse`
    該屬性決定主軸的方向(即專案的排列方向)。
    row:主軸為水平方向,起點在左端。
    row-reverse:主軸為水平方向,起點在右端。
    column(預設值):主軸為垂直方向,起點在上沿。
    column-reverse:主軸為垂直方向,起點在下沿。

flexWrap容器屬性: `nowrap | wrap | wrap-reverse`
    預設情況下,專案都排在一條線(又稱"軸線")上。flex-wrap屬性定義,如果一條軸線排不下,如何換行。
    nowrap(預設值):不換行
    wrap:換行,第一行在上方
    wrap-reverse:換行,第一行在下方。(和wrap相反)

justifyContent容器屬性:`flex-start | flex-end | center | space-between | space-around`
    定義了伸縮專案在主軸線的對齊方式
    flex-start(預設值):伸縮專案向一行的起始位置靠齊。
    flex-end:伸縮專案向一行的結束位置靠齊。
    center:伸縮專案向一行的中間位置靠齊。
    space-between:兩端對齊,專案之間的間隔都相等。
    space-around:伸縮專案會平均地分佈在行裡,兩端保留一半的空間。

alignItems容器屬性:`flex-start | flex-end | center | baseline | stretch`
    定義專案在交叉軸上如何對齊,可以把其想像成側軸(垂直於主軸)的“對齊方式”。
    flex-start:交叉軸的起點對齊。
    flex-end:交叉軸的終點對齊 。
    center:交叉軸的中點對齊。
    baseline:專案的第一行文字的基線對齊。
    stretch(預設值):如果專案未設定高度或設為auto,將佔滿整個容器的高度。

flex專案屬性:
“flex-grow”、“flex-shrink”和“flex-basis”三個屬性的縮寫,
 其中第二個和第三個引數(flex-shrink、flex-basis)是可選引數。預設值為“0 1 auto”。
 自身相對於父容器的權重佔比

alignSelf專案屬性:
“auto | flex-start | flex-end | center | baseline | stretch”
align-self屬性交叉軸允許單個專案有與其他專案不一樣的對齊方式,可覆蓋align-items屬性。
預設值為auto,表示繼承父元素的align-items屬性,如果沒有父元素,則等同於stretch。

五、高階使用 ScrollView 可滾動的容器,可放入多個元件和檢視,元件並不需要是同類型的。 ScrollView不僅可以垂直滾動,還能水平滾動(通過horizontal屬性來設定)

ScrollView必須有一個確定的高度才能正常工作,
實際上所做的就是將一系列不確定高度的子元件裝進一個確定高度的容器(通過滾動操作)

ScrollView和ListView/FlatList區別:
    ScrollView會簡單粗暴地把所有子元素一次性全部渲染出來。
    ListView會惰性渲染子元素,只在它們將要出現在螢幕中時開始渲染。
    FlatList是0.43版本開始新出的改進版的ListView,效能更優

<ScrollView style={{height: 200}}> 
    <Text style={{fontSize:96}}>Scroll me plz</Text> 
    <Image source={require('./img/favicon.png')} /> 
    <Image source={require('./img/favicon.png')} /> 
    <Image source={require('./img/favicon.png')} /> 
    <Image source={require('./img/favicon.png')} /> 
    <Image source={require('./img/favicon.png')} />
</ ScrollView>

長列表:FlatList或是SectionList FlatList元件用於顯示一個垂直的滾動列表,其中的元素之間結構近似而僅資料不同。

FlatList更適於長列表資料,且元素個數可以增刪。
和ScrollView不同的是,FlatList並不立即渲染所有元素,而是優先渲染螢幕上可見的元素。

FlatList元件必須的兩個屬性是data和renderItem。
data是列表的資料來源,而renderItem則從資料來源中逐個解析資料,然後返回一個設定好格式的元件來渲染。


列表:
<FlatList 
    //資料來源
    data={[ {key: 'Devin'}, {key: 'Jackson'}, {key: 'James'},
     {key: 'Joel'}, {key: 'John'}, {key: 'Jillian'}, {key: 'Jimmy'}, {key: 'Julie'}, ]} 

    //Item顯示元件
    renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>} 
/>

分組列表
<SectionList 
    sections={[ {title: 'D', data: ['Devin']},
     {title: 'J', data: ['Jackson', 'James', 'Jillian', 'Jimmy', 'Joel', 'John', 'Julie']}, ]} 

    renderItem={({item}) => <Text style={styles.item}>{item}</Text>} 
    renderSectionHeader={({section}) => <Text style={styles.sectionHeader}>{section.title}</Text>}
/>
    //請求路徑
    fetch("https://mywebsite.com/endpoint/",
    //請求設定
    {   //請求方法
        method: "POST",
        //設定請求頭   
        headers: {
            Accept: "application/json",
            "Content-Type": "application/json"
        },
        //設定請求體,post;get沒有body
        body: JSON.stringify({
            firstParam: "yourValue",
            secondParam: "yourOtherValue"
        })
    });

獲取響應,解析資料:
    //請求的網路路徑
    fetch("https://facebook.github.io/react-native/movies.json")
    //通過箭頭函式,資料解析,返回解析後的json物件
    .then(response => response.json())
    //接收解析後的json物件,獲取有用資料,在狀態機中做資料重新整理
    .then(responseJson => {
        responseJson.movies;
    })
    //請求錯誤情況下進行呼叫
    .catch(error => {
        console.error(error);
    });

箭頭函式:
    (abc)=>(  <Text/>  )   :   返回<Text/> 
    簡寫:
    abc  =>  <Text/>


    (abc)=>{  <Text/>  }   :  函式體執行一個<Text/>,無返回值


例項:
    constructor(props) {
        super(props);

        this.state = {
            dataValue: []
        };
    }

    componentDidMount() {
        fetch("https://facebook.github.io/react-native/movies.json")
        .then(response => response.json())
        .then(responseJson => {
            //重新整理資料
            this.setState({
            dataValue: responseJson.movies
            });
        })
        .catch(error => {
            console.log(error);
        });
    }


    render() {
        return (
        <View style={style.root}>
            <FlatList
                data={this.state.dataValue}
                renderItem={({ item }) => (
                    <Text>{item.title}</Text>
                )}
            />
        </View>
        );
    }

六、整合原生專案 整合到現有原生應用 1.建立RN專案 2.AS中建立原生Android專案 3.將RN中自帶的RNActivity,RNApplication頁面,匯入到Android原生專案中: 1)匯入RN依賴 在你的app中 build.gradle 檔案中新增 React Native 依賴: dependencies { … implementation “com.facebook.react:react-native:+” // From node_modules. }

        在專案的 build.gradle 檔案中為 React Native 新增一個 maven 依賴的入口,必須寫在 "allprojects" 程式碼塊中:
        allprojects { 
            repositories { 
                ... 
                maven {
                // All of React Native (JS, Android binaries) is installed from npm 
                    url "$rootDir/../node_modules/react-native/android" 
                } 
            } 
        ... 
        }
    2)在 AndroidManifest.xml 清單檔案中宣告網路許可權:
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
        DevSettingsActivity 介面(即開發者選單),則還需要在 AndroidManifest.xml 中宣告:
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

    3)在AndroidManifest.xml中宣告RNActivity,RNApplication
        <application
            android:name=".RNApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">

            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>

            <activity android:name=".RNActivity"></activity>
            <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
        </application>        

    4)通過android專案點選事件,啟動RN檢視
        Intent intent = new Intent(MainActivity.this, RNActivity.class);
        startActivity(intent);

4)將android原生專案,匯入到RN/android目錄:最編譯執行
5)執行app專案,啟動RN服務即可

七、路由導航: 路由分類: StackNavigator 跳轉頁面,傳值 TabNavigator 左右切換導航欄 createBottomTabNavigator 底部導航欄(圖示) createSwitchNavigator 身份驗證選擇

首先是在你的應用中安裝此庫: yarn add react-navigation

1)StackNavigator路由表: 配置路由表: import { StackNavigator } from “react-navigation”; import Page1 from “./Page1”; import Details1 from “./Details1”;

const RouteABC = StackNavigator(
    {
        P: { screen: Page1 },
        D: { screen: Details1 }
    },
    {
        initialRouteName: "P"
    }
);

跳轉頁面,傳值取值:

//跳轉到D對應的頁面,傳遞name,age引數
this.props.navigation.navigate("D", { name: "張三", age: "123" });

//在D頁面中取值
 {this.props.navigation.getParam("name", "AAA")}

配置標題: //直接設定標題 static navigationOptions = { title: “Page1” }; static navigationOptions = { header: null };

//獲取傳遞的引數,修改為標題文字
static navigationOptions = ({ navigation }) => ({
    title: navigation.getParam("name", "Abc")
});

//更改標題樣式
static navigationOptions = ({ navigation }) => ({
    title: navigation.getParam("name", "Abc"),
    headerStyle: {
        backgroundColor: "#f4511e"
    },
    headerTintColor: "#fff",
    headerTitleStyle: {
        fontWeight: "bold"
    }
});

//跨頁面共享通用的navigationOptions
const AppNvg = StackNavigator(
    {
        Main: { screen: HomeScreen },
        Profile: { screen: ProfileScreen },
        My: { screen: MyScreen }
    },
    {
        initialRouteName: "Main",
        navigationOptions: {
            headerStyle: {
                backgroundColor: "#f4511e"
            },
            headerTintColor: "#fff",
            headerTitleStyle: {
                fontWeight: "bold"
            }
        }
    }
);

2)Tab導航欄:(自帶路由功能) import { TabNavigator } from “react-navigation”;

import JHSreeen from “./JHSreeen”; import FXSreeen from “./FXSreeen”;

const TieScreen = TabNavigator( { JH: { screen: JHSreeen, navigationOptions: { title: “精華” } }, FX: { screen: FXSreeen, navigationOptions: { title: “分享” } } }, { //設定標題欄通配效果 navigationOptions: { title: “標題” }, tabBarPosition: “top”, //Tab擺放位置 //誰設定文字選中前後效果顏色 tabBarOptions: { activeTintColor: “white”, //啟用樣式 inactiveTintColor: “gray” //未啟用樣式 }, swipeEnabled: true, //是否可以滑動 animationEnabled: true //滑動效果 } );

3)底部導航欄: 使用三方相簿: /** * 圖示使用: * yarn add react-native-vector-icons * react-native link * * import Ionicons from “react-native-vector-icons/Ionicons”; * * navigationOptions中配置 */

import { createBottomTabNavigator } from “react-navigation”; import Ionicons from “react-native-vector-icons/Ionicons”;

const Home = createBottomTabNavigator( { Topic: { screen: Topic, navigationOptions: { title: “帖子” } }, Publish: { screen: Publish, navigationOptions: { title: “釋出” } }, My: { screen: My, navigationOptions: { title: “我的” } } }, { //誰設定文字選中前後效果顏色 tabBarOptions: { activeTintColor: “#FF0000”, //啟用文字圖片樣式 inactiveTintColor: “#0000FF”, //未啟用文字圖片樣式

  activeBackgroundColor: "#2296F3", //啟用背景樣式
  inactiveBackgroundColor: "#ffffff" //未啟用背景樣式
},
navigationOptions: ({ navigation }) => ({
  tabBarIcon: ({ focused, tintColor }) => {
    const { routeName } = navigation.state;
    let iconName;
    if (routeName === "Topic") {
      //切換不同的圖示
      //iconName = `ios-document${focused ? "" : "-outline"}`;
      //iconName = `${focused ? "ios-document" : "ios-document-outline"}`;
      iconName = "ios-document";
    } else if (routeName === "Publish") {
      iconName = "ios-create";
    } else if (routeName === "My") {
      iconName = "ios-person";
    }

    return <Ionicons name={iconName} size={25} color={tintColor} />;
  }
})

} );

4)身份驗證路由:

Route.js 身份驗證的路由頁面,主要用於配置認證頁面 import { createSwitchNavigator } from “react-navigation”; import HomeScreen from “./HomeScreen”; import SignInScreen from “./SignInScreen”; import AuthLoadingScreen from “./AuthLoadingScreen”;

const Route = createSwitchNavigator({ AuthLoading: { screen: AuthLoadingScreen }, Home: { screen: HomeScreen }, SignIn: { screen: SignInScreen } });

AuthLoadingScreen.js 判斷登入狀態,跳轉不同頁面

//判斷SP檔案中是否儲存了userToken欄位:true 登入狀態 false:未登入狀態(讀SP檔案狀態) _bootstrapAsync = async () => { //獲取登入狀態 const userToken = await AsyncStorage.getItem(“userToken”); //根據狀態判斷:跳轉不同頁面 this.props.navigation.navigate(userToken ? “Home” : “SignIn”); };

SignInScreen.js 進入登入頁面,說明未登入,要求使用者登入(將登入資訊儲存到SP檔案)