react-native的简单使用
一、网上搜集RNandroid的问题
二、目前存在的问题1、react-native库会直接带动整个编译环境提升到最高,否则编译不了。带来的影响是新的buildtool似乎把很多以前废弃的函数直接undfine了,即可能找不到该函数了。以前的很多业务代码报错,这些都是成本。 2、rn方法数超标的发生鉴于我们国内app各种sdk的使用,有些比如语音等第三方库的必不可少很容易导致dexIndexOverFlow,虽然这些是有解决方案,但是5.0以下可能导致不适发生。我怀疑RN是方便那些熟悉Web开发的人只需很少的学习成本就可以转入移动应用开发。并未听闻Google对RN的评价,考虑未来andromeda的发布,某些性能会带来变革。对于广大JavaScript出身,想做移动开发而又不想投入人力物力学原生的开发者来说,是个好时机。对于JavaScript出身的开发者,确实是一个拓宽自己职业前进道路的一门新技术,三端(Web,iOS,Android)尽收眼底,单想想就会令人兴奋不已。但是对于原本就是原生出身的开发者,和广大业务型驱动的项目,以及踩坑能力和扛风险能力都比较一般的非一线公司来讲,RN可以关注,可以业余时间来尝试和开拓眼界,其余的,收敛一下激动的小心脏,还是该干啥干啥,保持淡定,真正到了RN初步成熟的时候,再进军也不迟(知乎) 3、 任何以后不知道咋样。直至当前,任何Java、Objective-C、Swift等官方技术之外,号称新潮的原生解决方案,都有无数个坑,填了一个又来一个,没完没了的。 4、 个人意见不要作为主语言,可以另开分支单独研发测试。我们项目开始使用RN,填坑无数,RN官方更新太频繁。和原生相比还是有差距。Android官方发布很多版本,RN后续改动也挺大的。需不需要使用RN我觉得主要是考虑到页面变化比较频繁,而又不想通过发布新版本(其实很多第三方渠道审核的时候越来越苛刻了)实现版本的更新才需要使用RN,其实也是可以考虑使用webview,webview相信在Google不停的优化下现在比以前好很多。RN其实有点想从开发中间拦截一次一统江湖的愿景,让大家只需要学习使用RN即可,但我想Google不会坐视不理的,一定会维护自己的地位。 三、运行官网demo在运行官方第一个demo:AwesomeProject的时候需要修改几个地方: 首先说第一个问题: 四、android源生app集成react Native的步骤1、先按照官方的步骤集成;1) 在项目的根目录:npm init生成的package.json需要在scripts处添加: 2) 在项目的根目录:npm install –save react react-native3) Curl –o .flowconfighttps://raw.githubuser content.com/facebook/react-native/master/.flowconfig 4) 在根目录创建index.android.js文件5) 在android studio项目的build.gradle添加:dependencies {
...
compile "com.facebook.react:react-native:+" // From node_modules.
}
6) 在android studio工程的build.gradle添加:allprojects {
repositories {
...
maven {
// All of React Native (JS,Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
...
}
注意去掉.. ,最后的:url “$rootDir/node_modules/react-native/android” 7) 在android studio项目里添加:<uses-permission android:name="android.permission.INTERNET" />
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
8) 然后实现官方的MyReactActivity代码:package com.rndemo.reactnativedemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(true) //BuildConfig.DEBUG
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager,"HelloWorld",null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause(this);
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this,this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostDestroy(this);
}
}
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
@Override
public boolean onKeyUp(int keyCode,KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode,event);
}
}
其中配置文件: android:theme="@style/Theme.AppCompat.Light.NoActionBar">
9)最后:react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
其中 your-company-name在demo中是: react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest
dest app/src/main/res/
当然别忘记在main的文件夹下创建assets文件夹,否则会报错:找不到文件夹。 2、遇到的坑,需要修改的地方:1) 红屏异常:Could not get BatchedBridge,make sure your bundle is packaged correctly网上有解决方案一或者方案二。 2) npm start 和 react-native start(等同react-native run-android)命令这两个命令都可以启动开发服务器,亲测,但不知道有什么区别。 五、JSX语法在 JavaScript 代码里写着 XML 格式的代码称为 JSX,HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写。React 官方推荐使用JSX, 当然你想直接使用纯Javascript代码写也是可以的,只是使用JSX,组件的结构和组件之间的关系看上去更加清晰。JSX 类似于 HTML,但不完全一样 js 代码:
1. //使用JSX
2. React.render(
3. <div>
4. <div>
5. <div>content</div>
6. </div>
7. </div>,8. document.getElementById('example')
9. );
10. 11. //不使用JSX
12. React.render(
13. React.createElement('div',null,14. React.createElement('div',15. React.createElement('div','content')
16. )
17. ),18. document.getElementById('example')19. );
render 是 React 的最基本方法,用于将模板转为 HTML 语言 六、React1、react定义React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件,所有组件类都必须有自己的 render 方法。注意,组件类的第一个字母必须大写,否则会报错。示例: var HelloMessage = React.createClass({
render: function() {
return <h1>
Hello {this.props.name}
</h1><p>
some text
</p>;
}
});
上面代码会报错,因为HelloMessage组件包含了两个顶层标签:h1和p。组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 ,就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。 getDefaultProps
getInitialState
componentWillMount
render
ComponentDidMount
对于该组件类所有后续应用,将会看到下面的方法依次被调用: getInitialState
componentWillMount
render
componentDidMout
(存在期)随着应用状态的改变,以及组件逐渐受到影响,下面的方法依次被调用: componentwillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
对于一个组件render是唯一一个必需的方法,并且有特定的规则: 2、props的解释this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。这里需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。 Bundle bundle = new Bundle();
bundle.putString("key01","value01");
mReactRootView.startReactApplication(mReactInstanceManager,"MyToastAndroid",bundle);
在react native出取值的方法: this.props.key01;
3、虚拟DOM组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。 4、this.state组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。 5、rn和原生通信1)Android向JS传递事件2)AndroidJS被动向Android询问事件消息示例: @ReactMethod
public void callBackTime(String name,Callback callback) {
callback.invoke("your name");
}
调用: MyToastAndroid.callBackTime("Allure",(msg) => { console.log(msg); ToastAndroid.show(msg,ToastAndroid.SHORT); });
3)promiseReact Native的跨语言访问是异步进行的,所以想要给JavaScript返回一个值的唯一办法是使用回调函数或者发送事件。 @ReactMethod
public void getPromiseInfo(String name,Promise promise) {
WritableMap writableMap=new WritableNativeMap();
writableMap.putString("age","20");
writableMap.putString("time","2016");
promise.resolve(writableMap);
}
接收:
MyToastAndroid.getPromiseInfo("Allure").then(msg=> {
console.log("年龄:" + msg.age + "/n" + "时间:" + msg.time);
ToastAndroid.show("Promise收到消息:" + "n" + "年龄:" + msg.age + "时间:" + msg.time,ToastAndroid.SHORT)
this.setState({
age: msg.age,time: msg.time,})
}).catch(error=> {
console.log(error);
});
6、自定义原生模块1)写源生模块类,类似JS里面的Component功能。需要继承ReactContextBaseJavaModule。例如:MyToastModule;2)写包类,作用是把模块类送到React Native中,实现 ReactPackage。例如:ToastReactPackage
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new MyToastModule(reactContext));
return modules;
}
3)需要把这个包类放到需要引入的Activity里面,因为模块类其实可以类比一个控件,最终需要显示出来,相当于布局吧。例如:mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.addPackage(new AnExampleReactPackage())
.setUseDeveloperSupport(true) //BuildConfig.DEBUG
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
Bundle bundle = new Bundle();
bundle.putString("key","来自原生代码");
mReactRootView.startReactApplication(mReactInstanceManager,bundle);
setContentView(mReactRootView);
4)以上三步骤完成后就可以使用了。例如:var MyToastAndroid = NativeModules.MyToastAndroid;
MyToastAndroid.show("sssss",MyToastAndroid.SHORT);
7、路由(route)使用导航器经常会碰到“路由(route)”的概念。“路由”车厢自现实生活中的路牌,在RN中专指包含了场景信息的对象。renderScene方法是完全根据路由提供的信息来渲染场景的。 七、ES6语法1、函数参数设置默认值function log(x,y = 'World') {
console.log(x,y);
}
2、typeof 运算符typeof 运算符把类型信息当作字符串返回。typeof 返回值有六种可能: “number,” “string,” “boolean,” “object,” “function,” 和 “undefined.” 最后存在的问题1、在运行别人的代码的时候执行:compile “com.facebook.react:react-native:+”加载的包始终是react-native-0.20.1. 2、执行:react-native start 3、出现:cant find variable:Componentimport React { Component } from ‘react’; 修改为import React,{ Component } from ‘react’; 4、出现的问题Could not connect to development server.解决办法:红屏引进有提示了。最可能的问题是:adb reverse tcp:8081 tcp:8081 5、Your app does not have the latest code changes because it was restarted manually.Please run from IDE instead.6、Application XXX has not been registered.This is either due to a require() error during initialization or failure to call AppRegistry.registerComponent.解决办法:定义的模块名称保存一致: 7、自定义Style的时候就会报错。解决的办法:首先导入包:StyleSheet 8、https://github.com/ldn0x7dc/react-native-media-kit/issues/27没有解决的问题:1、 exports的使用exports.displayName = ‘ButtonExample’; 2、(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |