ReactNative总结

一、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网络请求:
发起请求,设置参数:
fetch(“https://mywebsite.com/mydata.json0?data=1”);

    //请求路径
    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)底部导航栏:
使用三方图库:
/**

  • 图标使用:
    react-native init Ab4 --version 0.55.4
    yarn add react-navigation

    yarn add react-native-vector-icons
    react-native link

    yarn add react-native-refresh-list-view

    yarn add react-native-render-html

    react-native run-android

  • 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文件)
<Button
title={“登录”}
onPress={async () => {
//登录,设置登录数据
await AsyncStorage.setItem(“userToken”, “abc”);
//跳转到主页面
this.props.navigation.navigate(“Home”);
}}
/>

HomeScreen.js 进入主页面,说明已经登录成功了,用户有可能注销登录(将SP文件中的登录信息清空)
<Button
title={“注销”}
onPress={async () => {
//注销清空数据
await AsyncStorage.clear();
//跳转到登录页面
this.props.navigation.navigate(“SignIn”);
}}
/>

八、动画使用
constructor(props) {
super(props);

this.state = {
// 1. 初始化动画值
scale: new Animated.Value(0)
};
}

render() {
return (
<View style={{ flex: 1, justifyContent: “center”, alignItems: “center” }}>
<Animated.Text
style={{
// 2. 将动画值绑定到style的属性:opacity透明度
// opacity: this.state.fadeAnim,
transform: [{ scale: this.state.scale }]
}}
>
RN的动画使用
</Animated.Text>

    <Button title="开启动画" onPress={this.press} />
  </View>
);

}

press = () => {
//3.动画处理以及开启
Animated.timing(this.state.scale, {
toValue: 3,
duration: 5000
}).start();
};

press = () => {
//3.动画处理以及开启
const animations = [
Animated.timing(this.state.opacity, {
toValue: 3,
duration: 5000
}),
Animated.timing(this.state.width, {
toValue: 500
}),
Animated.timing(this.state.height, {
toValue: 500
})
];

Animated.stagger(5000, animations).start();
};

九、常用控件以及常用Api
详情见RN中文官网

十、其他知识点:
热更新,普通更新:
更新:apk包下载更新
热更新:assets/index.adnroid.bundle资源文件包

离线打包:
    1.手动创建assets文件夹:
        android\app\src\main\assets

    2.在RN根目录,生成离线包:
    react-native bundle --platform android --dev false --entry-file index.js 
    --bundle-output android/app/src/main/assets/index.android.bundle 
    --assets-dest android/app/src/main/res/

    生成以后的包:
        android\app\src\main\assets:
            index.android.bundle
            index.android.bundle.meta

assets与raw的区别:
    共同点:放置资源文件,并且原封不动的打包到apk中
    不同点:
        assets:不会生成R.id.XXX,访问需要用AssetManager进行访问;可以创建多级文件夹
        raw:会成才R.raw.XXX;不可以创建文件夹


adb调试:
    android devices debug:安卓设备调试工具

    AS 与 模拟器或者手机进行连接


打包签名:
    签名作用:上线,统一版本;提高安全性 
    签名文件:.jks   文件密码   别名    别名密码    .....    一定要妥善保管
    AS签名:build--->Gerneris Singl Apk


网络三要素:
    ip  端口号   协议


手机x64安装不上问题解决:支持x86的使用
    将以下代码,添加到app/build.gradle:

        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
        packagingOptions {
            exclude "lib/arm64-v8a/libimagepipeline.so"
        }


原生模块,原生组件:
    固定操作,按代码一步步执行

十一、项目开发
分析用到的知识点
搭建框架(分析如何搭建,搭建思路)
创建项目,编译运行(初始版本)
编写模块代码。。。。。。
提交代码管理工具,做备份

十二、RefreshListView、HTML

RefreshListView实现上拉加载更多,下拉刷新数据:

使用之前导入依赖:

yarn  add  react-native-refresh-list-view
import RefreshListView, { RefreshState } from "react-native-refresh-list-view";

<RefreshListView
data={this.state.dataValue}
renderItem={({item})=>()}
keyExtractor={index => (index))}

refreshState={this.state.refreshState}
onFooterRefresh={this.FooterRefresh}
onHeaderRefresh={this.HeaderRefresh}    

重要状态:
RefreshState.Idle
RefreshState.HeaderRefreshing
RefreshState.FooterRefreshing
RefreshState.Failure

使用步骤:
class Item extends Component {
render() {
return (

{this.props.title}
<View style={{ flexDirection: “row” }}>
<Image
source={{ uri: this.props.url }}
style={{ width: 100, height: 100 }}
/>
{this.props.name}


);
}
}
constructor(props) {
super(props);

    this.state = {
        page: 1,
        dataValue: [],
        refreshState: RefreshState.Idle
    };
}

componentDidMount() {
    this.HeaderRefresh();
}

HeaderRefresh = () => {
    this.setState({
    page: 1,
    refreshState: RefreshState.HeaderRefreshing
    });

    fetch(`https://cnodejs.org/api/v1/topics?page=1&tab=good&limit=10`)
    .then(response => response.json())
    .then(responseJson => {
        this.setState({
        dataValue: responseJson.data,
        refreshState: RefreshState.Idle,
        page: this.state.page + 1
        });
    })
    .catch(error => {
        this.setState({
        refreshState: RefreshState.Failure
        });
    });
};

FooterRefresh = () => {
    this.setState({
    refreshState: RefreshState.FooterRefreshing
    });

    fetch(
    `https://cnodejs.org/api/v1/topics?page=${
        this.state.page
    }&tab=good&limit=10`
    )
    .then(response => response.json())
    .then(responseJson => {
        this.setState({
        dataValue: [...this.state.dataValue, ...responseJson.data],
        refreshState: RefreshState.Idle,
        page: this.state.page + 1
        });
    })
    .catch(error => {
        this.setState({
        refreshState: RefreshState.Failure
        });
    });
};

render() {
    return (
        <View style={styles.container}>
            <RefreshListView
            style={styles.welcome}
            data={this.state.dataValue}
            renderItem={({ item }) => {
                return (
                    <TouchableHighlight
                        onPress={() => {
                        this.props.navigation.navigate("Details", {
                            title: item.title,
                            content: item.content
                        });
                        }}
                    >
                        <Item
                        url={item.author.avatar_url}
                        title={item.title}
                        name={item.author.loginname}
                        />
                    </TouchableHighlight>
                );
            }}
            keyExtractor={index => {
                return index;
            }}
            refreshState={this.state.refreshState}
            onFooterRefresh={this.FooterRefresh}
            onHeaderRefresh={this.HeaderRefresh}
            />
        </View>
    );
}

}

Html:
用于加载HTML页面片段

导入依赖:
    yarn add react-native-render-html

    import HTML from "react-native-render-html"; //渲染html成原生内容

    <ScrollView>
        <HTML
            style={styles.welcome}
            html={this.props.navigation.getParam("content", "content")}
        />
    </ScrollView>

十三、原生模块、原生ui组件、原生交互传值

1.定义Module类:
public class CommunicationModule extends ReactContextBaseJavaModule {

    private static final String LONG_TIME = "LONG";
    private static final String SHORT_TIME = "SHORT";

    public CommunicationModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "CommunicationModule";
    }

    @Override
    public Map<String, Object> getConstants() {
        Map<String, Object> constants = new HashMap<>();
        constants.put(LONG_TIME, Toast.LENGTH_LONG);
        constants.put(SHORT_TIME, Toast.LENGTH_SHORT);
        return constants;
    }

    //代表改方法是给RN使用
    @ReactMethod
    public void show(int duration) {
        Toast.makeText(getReactApplicationContext(), "message:" + duration, duration).show();
    }

    /**xxxxxxxxxxxxxxxxxxx重点
    *
    * js给android传值:通过方法的参数传递即可
    *
    * android给js传值:callback回调函数即可
    */
    @ReactMethod
    public void testAndroidCallbackMethod(String msg, Callback callback) {
        //msg是js给android传递的参数
        Toast.makeText(getReactApplicationContext(), msg, Toast.LENGTH_LONG).show();
        //android给js传值使用:callback回调函数即可
        callback.invoke("lzj123134545");
    }

    @ReactMethod
    public void textAndroidPromiseMethod(String msg, Promise promise) {
        //msg是js给android传递的参数
        Toast.makeText(getReactApplicationContext(), msg, Toast.LENGTH_SHORT).show();
        //android给js传值使用:promise异步编程返回
        promise.resolve("android给js传值使用");
    }

    //获取Intent传值
    @ReactMethod
    public void getDataFromIntent(Callback callback) {
        try {
            Activity currentActivity = getCurrentActivity();
            String result = currentActivity.getIntent().getStringExtra("name");
            if (TextUtils.isEmpty(result)) {
                callback.invoke("no_data");
            } else {
                callback.invoke(result);
            }
        } catch (Exception e) {
            callback.invoke("error");
        }
    }
}       

2.定义Package类:
public class CommunicationPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> list = new ArrayList<>();
        list.add(new CommunicationModule(reactContext));
        return list;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        List<ViewManager> list = new ArrayList<ViewManager>();
        return list;
    }
}    


3.将Package类写入到Application 中:
@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
          new CommunicationPackage()
  );
}


4.js使用:

Communication.js
    //引用原生模块
    import { NativeModules } from "react-native";

    //使用原生模块
    export default NativeModules.CommunicationModule;

CommunicationTest.js:测试使用类
    import Communication from "./Communication";

    export default class CommunicationTest extends Component {
        constructor(props) {
            super(props);

            this.state = {
              data: "Welcome to React Native!"
            };
        }

        componentDidMount() {
            Communication.getDataFromIntent(result => {
                this.setState({
                    data: result
                });
            });
        }

        render() {
            return (
            <View style={styles.container}>
                <Text
                style={styles.welcome}
                onPress={() => {
                    // Communication.show(100);


                    // Communication.testAndroidCallbackMethod("dasdasdasdas", result => {
                    //   Alert.alert(result);
                    // });


                    // Communication.textAndroidPromiseMethod("abcx")
                    //   .then(result => {
                    //     Alert.alert(result);
                    //   })
                    //   .catch(error => {
                    //     Alert.alert(error);
                    //   });

                }}
                >
                {this.state.data}
                </Text>
            </View>
            );
        }
    }        
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值