react、react native、webStorm、vscode介绍
1、react是facebook开源的一套申明式js前端框架,React 是基础框架,是一套基础设计实现理念,开发者不能直接使用它来开发移动应用或者网页,发展出了React.js 框架来开发网页
2、react native是在React框架之上,用前端的技术将jsx通过babel编译成reactElement,在创建对应的原生组件在移动端运行的app,性能比原生应用差
react native 环境配置
参考教程
face book官方建议使用Chocolatey安装Python2、nodejs
安装Chocolatey
管理员身份打开windowns的CMD,输入
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
安装nodejs、python
重新打开一个cmd窗口,输入安装指令
choco install -y nodejs.install python2
安装React Native命令行界面
npm install -g react-native-cli
Android开发环境配置(略)
创建RN项目
AwesomeProject为工程名,按实际情况自定义,输入指令后一直确定即可
react-native init AwesomeProject
编译Android项目
检查是否配置成功,故障排查
cd AwesomeProject
react-native run-android
react native 集成到现有android工程
设置目录结构(可跳过)
为确保顺畅体验,请为集成的React Native项目创建新文件夹,然后将现有Android项目复制到/android子文件夹
配置package.json
工程根目录下新建package.json文件,输入内容
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "yarn react-native start"
}
}
安装react和react-native包
工程根目录下打开终端,依次输入
yarn add react-native
yarn add react@version_printed_above
集成React Native到Android工程
按照此配置如果不能成功点亮工程,可以逆向思维,将android工程直接拷贝到RN工程的android目录,反向操作实现集成
添加依赖
implementation "com.facebook.react:react-native:+"
配置maven
maven {
// All of React Native (JS, Android binaries) is installed from npm
//设置目录机构时将android工程移到android文件夹时使用此路径,否则使用下面的路径
url "$rootDir/../node_modules/react-native/android"
// url "$rootDir/node_modules/react-native/android" //
}
配置AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
配置Application和activity
1、新建RNPageActivity继承ReactActivity,getMainComponentName方法返回值与package.json中的name标签值相同
class RNPageActivity : ReactActivity() {
override fun getMainComponentName(): String {
return "MyReactNativeApp"
}
}
2、Application实现接口ReactApplication重写getReactNativeHost方法
class MyApp : BaseApplication(), ReactApplication {
override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
}
override fun getReactNativeHost(): ReactNativeHost {
return mReactNativeHost
}
private val mReactNativeHost = object : ReactNativeHost(this) {
override fun getUseDeveloperSupport(): Boolean {
return com.topband.base.BuildConfig.DEBUG
}
override fun getPackages(): List<ReactPackage> {
//此处配置RN与原生通信模块
return listOf<ReactPackage>(
MainReactPackage()
)
}
override fun getJSMainModuleName(): String {
return "index"
}
}
}
测试您的集成
1、工程根目录新建index.js文件,输入内容
MyReactNativeApp对应package.json中的name
import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
class HelloWorld extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello, World</Text>
</View>
);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent('MyReactNativeApp', () => HelloWorld);
2、项目根目录打开终端输入指令启动服务后
yarn start
3、正常构建并运行您的Android应用,正常情况会看到终端提示服务启动成功,编译后的app启动RNPageActivity能加载RN界面显示“Hello, World”
Android与RN相互通信
创建ReactContextBaseJavaModule子类
将需要暴露接口的原生类继承ReactContextBaseJavaModule
public class TestNative extends ReactContextBaseJavaModule {
public TestNative(@Nonnull ReactApplicationContext reactContext) {
super(reactContext);
}
@Nonnull
@Override
public String getName() {
//暴露给js的名称,js通过名称找到本类
return "test";
}
}
注解标记方法
使用@ReactMethod注解标记方法
@ReactMethod
public void test(int data, Callback callback) {
// todo
callback.invoke("这里可以回调到RN");
}
创建ReactPackage子类
新建一个类实现ReactPackage接口,重写createNativeModules方法,将需要注册的本地模块添加进去
public class TestPackages implements ReactPackage {
@Nonnull
@Override
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
//将需要注册的本地模块添加到list返回
List<NativeModule> list = new ArrayList<>();
list.add(new TestNative(reactContext));
return list;
}
}
配置的Application
前面配置的Application中找到getPackages方法,将TestPackages返回
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
//这里将TestPackages添加进去
packages.add(new TestPackages());
return packages;
}
RN页面使用原生接口
//导入NativeModules
import { NativeModules } from 'react-native';
//找到原生模块,此处的test与TestNative类中getName方法返回的值一致
const testNative = NativeModules.test;
//调用原生方法
testNative.test(111, function (e) {
// todo
})
支持的参数类型
java类型 | js类型 |
---|---|
Boolean | Bool |
Integer | Number |
Double | Number |
Float | Number |
String | String |
Callback | function |
ReadableMap | Object |
ReadableArray | Array |
原生主动发送事件到JavaScript
androi原生发送事件是通过ReactApplicationContext完成。eventName为自定义名称,原生与js层保持一致即可。可以通过不同的eventName定义多种类型事件。事件发送ios和android有部分差异,可以查阅官方关于iso事件发送或者咨询ios开发
mReactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("eventName", params);
RN界面注册事件监听
DeviceEventEmitter.addListener('eventName', function(data){
});
RN使用原生View
创建ViewManager子类
以TextView举例,新建ReactTextManager继承SimpleViewManager
public class ReactTextManager extends SimpleViewManager<TextView> {
@Nonnull
@Override
public String getName() {
//注册名称,js端通过此名称找到本类
return "testTextView";
}
}
重写方法 createViewInstance
ReactTextManager类中重写createViewInstance方法,实例化一个TextView
@Nonnull
@Override
protected TextView createViewInstance(@Nonnull ThemedReactContext reactContext) {
//实例化TextView
TextView textView = new TextView(reactContext);
textView.setTextColor(0xffff0000);
textView.setTextSize(20);
return textView;
}
使用@ReactProp(或@ReactPropGroup)注解
定义一个setText方法,@ReactProp注解标记后js层可以通过name设置的值直接调用此方法
@ReactProp(name = "text")
public void setText(TextView textView, String text) {
//暴露setText方法
Log.i("test", "setText:" + text);
if (textView != null) {
textView.setText(text);
}
}
注册 ViewManager
创建ReactPackage子类,重写createViewManagers方法,实例化ReactTextManager并返回
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
List<ViewManager> views = new ArrayList<>();
views.add(new ReactTextManager());
return views;
}
JavaScript中使用原生view
导入requireNativeComponent模块
import { requireNativeComponent } from 'react-native';
利用requireNativeComponent找到testTextView,名称为ReactTextManager中getName方法返回的值
const testTextView = requireNativeComponent('testTextView');
使用testTextView。代码中text="22323"表示调用ReactTextManager类中被@ReactProp(name = "text")注解的方法setText,第一个参数TextView会自动传递一个TextView实例,第二个字符串参数为我们设置的值“22323”
<testTextView text="22323" style={{backgroundColor: '#ffffff', width: 120, height: 50}}/>
开始开发RN
后面的讲述基于RN工程配置成功,能正常编译运行
1、导包,一般情况要导入React、StyleSheet(样式)和需要使用的UI标签、其它扩展库、自己的js库
import React from 'react';
import {StyleSheet, View} from 'react-native';
2、继承React.Component
export default class 类命 extends React.Component {
}
3、重写render方法
注意,return返回的内容用括号包裹,举例中的View标签可以替换为其它标签
render(): React.ReactNode {
return (
<View >
</View>
)
}
4、编写Style样式
使用React Native,您不会使用特殊语言或语法来定义样式。只需使用JavaScript设置应用程序的样式。RN中一个标签可以使用多个style修饰,多个style直接继承并扩展,例如 定义pageBg,pageBg2
const styles = StyleSheet.create({
pageBg: {
flex: 1,
},
pageBg2: {
backgroundColor: '#eff2f7',
},
}
使用style,此时View标签样式为flex: 1 并且 backgroundColor: '#eff2f7'
<View style={styles.pageBg , styles.pageBg2 }>
</View>
也可以直接在标识上写style,两种方式等同
<View style={{ flex: 1}, {backgroundColor: '#eff2f7' }}>
</View>
5、可变属性state
RN控制组件有两种类型的数据:props和state。props由父项设置,props的值在组件的整个生命周期内都是固定的。state需要在constructor方法中定义,state在当前界面修,每次调用setState都会重新执行 render 方法渲染界面。setState 是一个合并操作,每次操作只修改指定属性,不影响其他属性,注意setState 是异步操作,修改不会马上生效
constructor(props) {
super(props);
this.state = { next: false },
};
}
使用、修改
//使用
this.state.xxx
//修改
this.setState(previousState => {
return { xxx: !previousState.xxx };
})
6、不可变属性props
this.props.maxLength RN控制组件有两种类型的数据:props和state。props由父项设置,props的值在组件的整个生命周期内都是固定的
this.props.xxx
配置界面导航(选配)
需要使用界面跳转必须配置,单页面无需配置
FB官方文档
React Native Navigation
1、安装依赖
npm install --save react-navigation
yarn add react-native-gesture-handler
yarn add react-navigation-stack
2、配置导航界面 这里的HomeScreen、ProfileScreen为自定义界面,按照实际项目修改
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
const MainNavigator = createStackNavigator({
Home: {screen: HomeScreen},
Profile: {screen: ProfileScreen},
});
const AppNavigator = createAppContainer(MainNavigator);
export default AppNavigator;
3、使用AppNavigator
进行界面跳转之前,我们需要在先在某个界面中返回AppNavigator,RN中的界面跳转实际是自定义导航栈
return (
<AppNavigator/>
);
4、进行界面跳转
Profile对应步骤2中定义的Profile;{name: 'Jane'}是通过key-value方式向下一个界面传递参数,按照实际情况填写,非必须
navigate('Profile', {name: 'Jane'})}
navigationOptions配置
此配置在Android和ios的UI均采用原生标题栏,所以android和ios不一致,Android采用的是material design的标题栏
1、在单个界面中配置
static navigationOptions = ({navigation}) => ({
title: '这是title',
//title样式
headerTitleStyle: {
flex: 1,
textAlign: 'center',
color: '#ffffff',
fontSize: 18,
},
//标题栏样式
headerStyle: {
backgroundColor: '#2f4f68',
},
});
2、在导航配置时配置
const MainNavigator = createStackNavigator(
{
HomePage: {
screen: HomePage,
navigationOptions: {
header: null
}
},
},
defaultNavigationOptions: {
headerBackTitle: null,
headerTintColor: 'grey'
}
}
禁用标题栏
static navigationOptions = {
header: null,
};
Flexbox布局
flexDirection布局的主轴
- row: 水平轴方向排列
- column: 竖直轴方向排列,默认是竖直
- row-reverse:左右反转的水平轴方向排列
- column-reverse:上下反转的,竖直轴方向排列
- 官方文档
flex权重
- 当flex为一个正整数时,组件尺寸会具有弹性,并根据具体的 flex 值来按比例分配
- 当flex为 0 时,组件尺寸由width和height决定,此时不再具有弹性
- 当flex为-1 时,组件尺寸一般还是由width和height决定。但是当空间不够时,组件尺寸会收缩到minWidth和minHeight所设定的值
- 官方文档
justifyContent子元素沿着主轴的排列方式
- flex-start从头排到尾
- center居中向两端扩散
- flex-end从尾排到头
- space-around居中两端均匀分布
- space-between头尾两端均匀分布
- space-evenly均匀分布
- 官方文档
alignItems 子元素沿着次轴排列方式
- flex-start次轴从头开始
- center次轴居中
- flex-end次轴从尾开始
- stretch拉伸
- 区别alignContent,只对多行的item才有效果
- 对alignSelf属性的值进行自定义则会覆盖父类的AlignItems效果
- 官方文档
- 参考图片
alignContent
alignContent的布局效果和alignIems完全一致,alignContent只对多行的item才有效果,而后者对单行、多行都有效
官方文档
alignSelf
alignSelf区别于alignItems的是,alignSelf在item内部定义的,它的默认取值是auto,向上取父类alignItems的值,如果对alignSelf属性的值进行自定义则会覆盖父类的效果
官方文档
其它
其它布局介绍点击传送门