1.iOS 运行指定模拟器
react-native run-ios --simulator "iPhone 7 Plus"
第二次运行默认为上一次的模拟器,不过如果重新开启服务器的话,还是会恢复默认
2. 查看所有模拟器
iOS :xcrun simctl list devices
android : adb devices
3.android 运行到安卓模拟器出现问题
one
JS server already running.Building and installing the app on the device (cd android && ./gradlew installDebug)...FAILURE: Build failed with an exception.* What went wrong:Could not determine java version from '10.0.1'.* Try:Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.Could not install the app on the device, read the error above for details.Make sure you have an Android emulator running or a device connected and haveset up your Android development environment:https://facebook.github.io/react-native/docs/getting-started.html复制代码
解决方法: 在当前项目中,进入 android/gradle/wrapper/gradle-wrapper.properties
替换这个为: `distributionUrl=https://services.gradle.org/distributions/gradle-4.3-rc-2-all.zip
two
解决完上一个,可能还会出现
* What went wrong:A problem occurred configuring project ':app'.> Failed to notify project evaluation listener. > Could not initialize class com.android.sdklib.repository.AndroidSdkHandler复制代码
查看jdk版本:
javac -version
目前官网上说的只支持 Java Development Kit [JDK] 1.8,那就去下一个吧。
下载好之后,进入文件夹:
/Library/Java/JavaVirtualMachines
我这里还有一个 jdk-10.0.1.jdk
,不知道啥时候下的,感觉没啥用,进入刚下的 jdk1.8.0_181.jdk
->Contents
->Home
如果没有 .bash_profile
执行:touch .bash_profile
如果没有权限,则在前面加 sudo: sudo touch .bash_profile
,
vim .bash_profile
,粘贴这些信息:
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home #这个为home的路径,每一个都不一样,注意PATH=$JAVA_HOME/bin:$PATH:.CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.export JAVA_HOMEexport PATHexport CLASSPATH复制代码
使用 source .bash_profile
使配置生效
输入 echo $JAVA_HOME
显示刚才配置的路径
three
接下来还可能出现 adb: command not found
的问题,这个时候还是要在 .bash_profile
里修改一下文件内容,粘贴如下:
export ANDROID_HOME=/Users/liuyuhang/Library/Android/sdk
,这里的 export ANDROID_HOME= #你的安卓sdk路径
如果保存不成功,则用 sudo vim .bash_profile
打开
four
接下来运行成功,but,红屏,按照红屏提示一个一个解决吧。
-
第一种方法:
-
在终端输入
adb shell input keyevent 82
-
点击进入
Dev Settings
-
点击
Debug server host for device
-
输入你电脑的IP地址和端口号
-
重新运行
-
第二种方法
-
跟上面相同进入到输入端口号跟 ip
-
输入
localhost:8081
-
再在终端输入
adb reverse tcp:8081 tcp:8081
-
重新运行
five
出现
Unable to load script from assets 'index.android.bundle'...复制代码
解决办法原文引自网上大神:
* Go to your project directory and check if this folder exists android/app/src/main/assetsi) If it exists then delete two files viz index.android.bundle and index.android.bundle.metaii) If the folder assets doesn't exist then create the assets directory there.* From your root project directory docd android && ./gradlew clean* Finally, navigate back to the root directory and check if there is one single entry file called index.jsi) If there is only one file i.e. index.js then run following commandreact-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/resii) If there are two files i.e index.android.js and index.ios.js then run thisreact-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res* Now run react-native run-android复制代码
原理是不加载本地的 npm
six
如果还有问题,尝试关闭所有运行的相关程序,重新打开本地服务器操作;另外还有一些灵异事件还在探索中。。
4.iOS 清理 Xcode 缓存
如果发现 iOS 模拟器较多,在 Xcode 中清理一下多余的虚拟机
进入 ~/Library/Developer/Xcode
iOS DeviceSupport
为模拟器的文件夹
5.取消 Xcode 上多余 log
打开 Xcode,Xcode menu -> Product -> Edit Scheme...
Environment Variables -> Add -> Name:
"OS_ACTIVITY_MODE", Value:"disable"
重新运行
基础学习
1.flex
flex
设置为 1 后,是设置占据父容器除了其他子视图外剩下的全部的空间; 默认顶层视图需要用
2.Flexbox
布局
flexDirection:row
(row
为横向,column
为纵向),在react-native 里默认竖向justifyContent:flex-start
flex-start
:从第一个视图依次排序布局center
:所有子视图会以父视图的中心为基准来贴近flex-end
:所有视图贴往右边space-around
:稍微靠向两端的对齐排列space-between
:靠两遍space-evenly
:
3.按钮
4.导航栏
1.主推:react-navigation
在项目中安装:yarn add react-navigation
this.props.navigation.navigate('Mine');
this.props.navigation.goBack();
2.利用 react-navigation 完成界面的传值:
A->B,从B中将值传过来:
A中:
this.props.navigation.push('Provices',{ getCity:function(city,value){ self.setState({ city:city, value:value }) } })复制代码
B中:
if(this.props.navigation.state.params.getCity){ let city = data.label this.props.navigation.state.params.getCity(city,data.value) } this.props.navigation.goBack(null);复制代码
原理是在push进入B之前,传方法过去,并在B中通过city跟value的值回传给A
5.状态(state
):
组件的state
是可变的,它负责处理与用户的交互。在通过用户点击事件等操作以后,如果使得当前组件的某个state
发生了改变,那么当前组件就会触发render()
方法刷新自己。
6.render()
:
- 该函数是组件的渲染回调函数,该函数是必须实现的,并且必须返回一个组件或一个包含多个子组件的组件。
- 该函数可以被调用多次:初始化时的渲染以及
state
改变以后的渲染都会调用这个函数。
componentDidMount()
:
- 在初始化渲染执行之后立刻调用一次,也就是说,在这个函数调用时,当前组件已经渲染完毕了,相当于
iOS
开发中ViewController
里的viewDidLoad
方法。 - 通常在这个方法里执行网络请求操作。
componentWillReceiveProps(object nextProps)
:
- 在当前组件接收到新的 props 的时候调用。此函数可以作为 react 在 prop 传入之后, render() 渲染之前更新 state 的机会。新的props可以从参数里取到,老的 props 可以通过 this.props 获取到。
- 在初始化渲染的时候,该方法不会调用。
shouldComponentUpdate(object nextProps, object nextState)
shouldComponentUpdate: function(nextProps, nextState) { return nextProps.id !== this.props.id;}复制代码
当shouldComponentUpdate方法返回false时,讲不会执行render()方法,componentWillUpdate和componentDidUpdate方法也不会被调用
这常用在刷新很多数据的列表上有用。
- 在接收到新的 props 或者 state,将要渲染之前调用。如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false,这样组件就不会更新,减少了性能上不必要的损耗。
- 该方法在初始化渲染的时候不会调用
componentWillUnmount()
- 在组件从 DOM 中移除的时候立刻被调用。例如当前页面点击返回键跳转到上一页面的时候就会调用。
- 通常在这个方法里移除通知。
####7.module.exports
方法定义全局样式,比如:
module.exports ={ //cell分割线样式 cellBottomLineStyle: { height: 0.4, opacity:0.5, backgroundColor: 'darkgray', },}; 复制代码
8.用到的标签需要导入,比如用了 View 跟 Text,需要这样:
import { Platform, StyleSheet, Text, View} from 'react-native';复制代码
前面两个为库函数
####9.TabNavigator
使用,(现在弃用,因为会提示Method 'jumpToIndex' is deprecated. Please upgrade your code to use jumpTo instead 'Change your code from 'jumpToIndex(1)' to 'jumpTo('...')
),改用createBottomTabNavigator
10.PropTypes
的引入
引入方式为 import PropTypes from 'prop-types';
路由配置
screen:和导航的功能是一样的,对应界面名称,可以在其他页面通过这个screen传值和跳转。 navigationOptions:配置TabNavigator的一些属性{ * title:标题,会同时设置导航条和标签栏的title * tabBarVisible:是否隐藏标签栏。默认不隐藏(true) * tabBarIcon:设置标签栏的图标。需要给每个都设置} 复制代码
11.TextInput 的使用
1.要折行使用:multiline={true}
2.水印:placeholder='请填写备注'
3.从左上开始布局在style里写:
textAlign: 'left',textAlignVertical: 'top',复制代码
4.监听输入内容:
onChangeText={(text) => this.setState({ name: text })}
结束之后的方法:
onEndEditing={(event)=>{event.nativeEvent.text}}复制代码
5.属性:
- secureTextEntry:true 为密文
- autoCapitalize:
- none:不自动变为大写
- sentences:将每句话的首字母自动改成大写
- words:将每个单词的首字母自动改成大写
- characters:将每个英文字母自动改为大写
- autoFocus:true 为第一响应者
- editable :是否可编辑
6.Text 组件可以触发点击事件,而 View 组件没有
7.在安卓上需要给宽度才会显示,高度可以不给
TouchableOpacity 的使用
想要点击时没有闪烁,添加一个属性,将默认点击透明度设置为 1: activeOpacity = {1}
12.Image 的使用
- 属性:resizeMode
- stretch:图片被拉伸至与容器大小一致,可能会发生变形
- contain:容器完全容纳图片,图片等比例进行拉伸
- cover(默认):图片居中显示且不拉伸图片,超出的部分剪裁掉
- 获取图片的属性:
在线:Image.getSize(url, (_width, _height) => { });
本地:
3.模糊:blurRadius={20}
const orderImage = Image.resolveAssetSource(require('./images/orderNormal.png'));console.info(orderImage);复制代码
4.在 Android 上潜在的内存泄漏 Bug
在安卓中,加载一张尺寸远大于容器的图片,内存会突然猛涨,在这张图上下滑动,程序就直接因为内存不足而崩溃了如何解决呢?其实办法也很简单,只需要设置 Image 组件的 resizeMethod 属性为 resize 即可
状态栏的显示
复制代码
动画的实现
有些时候由于性能瓶颈,不得不放弃通过触发render的方式来改样式,而是通过setNativeProps 来直接更改原生组件的样式属性 来达到相同的效果
Date 日期的使用
转成时间:
getCurrentTime(){ var date = new Date(); // var timestamp2 = ( new Date()).valueOf(); // alert(timestamp2) var year = date.getFullYear().toString(); var month = (date.getMonth()+1).toString(); var day = date.getDate().toString(); var hour = date.getHours().toString(); var minute = date.getMinutes().toString(); return year+'/'+month+'/'+day+' '+hour+':'+minute }复制代码
时间转时间戳:
( new Date()).valueOf()复制代码
时间戳转时间:
//时间戳转时间 timestampToTime(timestamp) { var date = new Date(timestamp);//时间戳为10位需*1000,时间戳为13位的话不需乘1000 var Y = date.getFullYear() + '-'; var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-'; var D = date.getDate() + ' '; var h = date.getHours() + ':'; var m = date.getMinutes() + ':'; var s = date.getSeconds(); return Y+M+D+h+m+s; }复制代码
注意,时间戳必须不能是字符串
13.FlatList 的使用
index.toString()} onLayout={} data={this.state.loactionData} renderItem={({item}) => }> 复制代码
注意,如果有嵌套的 FlatList,需要把 keyExtractor 替换成 lisKey,还可以
listKey={(item, index) => 'A' + index.toString()}
2.遇到界面可能不会刷新问题:
如果是一个引用类型(Object或者数组都是引用类型),则需要先修改其引用地址(比如先复制到一个新的Object或者数组中),然后再修改其值,否则界面很可能不会刷新。
3.一行实现多列的方法:
FlatList 提供了一个叫 numColumns 的属性,你只需要设置一行的列数,便可轻松实现一行多列的
4.设置 getItemLayout,在高度固定的时候
getItemLayout={(data, index) => ( {length: scaleHeight(50), offset: scaleHeight(50) * index, index} )}复制代码
5.防止快速滑动出现白屏
设置 windowSize={xx} ,指的是屏幕外要渲染的数量
14. ScrollView的使用
监听滑动事件: onMomentumScrollEnd = {this.contentViewScroll}
注意:如果方法内会用到 this
,需要在 constructor(props)
方法里绑定 :this.contentViewScroll = this.contentViewScroll.bind(this);
15. Slider 使用
基本上颜色都可以做调整,除了大小
属性:
minimumValue:滑块的最小值(当滑块滑到最左侧时表示的值),默认为0
maximumValue:滑块的最大值(当滑块滑到最右端时表示的值),默认为1
value:滑块的初始值。这个值应该在最小值和最大值之间,默认值是0
onValueChange:在用户拖动滑块的过程中不断调用此回调,携带一个当前滑块的位置参数
onSlidingComplete:户结束滑动的时候调用此回调
step:滑块的最小步长,这个值应该在0到(maximumValue - minimumValue)之间,默认值为0
thumbImage:给滑块设置一张图片,只支持静态图片
trackImage:给轨道设置一张背景图,只支持静态图片,图片最中央的像素会被平铺直至填满轨道
minimumTrackImage:指定一个滑块左侧轨道背景图,仅支持静态图片。图片最右边的像素会被平铺直至填满轨道
maximumTrackImage:指定一个滑块右侧轨道背景图,仅支持静态图片。图片最左边的像素会被平铺直至填满轨道
minimumTrackTintColor:滑块左侧轨道的颜色,默认为一个蓝色的渐变色
maximumTrackTintColor:滑块右侧轨道的颜色,默认为一个灰色的渐变色
15. setState 属于异步调用
常见问题:
this.setState({key: 'value'},()=>{ console.log('这里获取最新的数据');});console.log('这里获取不到最新的数据');复制代码
16. 界面显隐的监听
利用 react-navigation 版本为 2.x 才有的方法,旧版本可以用 onNavigationStateChange + context,现在用 addListener 方法来监听 didFocus 或 didBlur 事件。
componentDidMount() { // 添加监听,消失的方法 // this.viewDidAppear = this.props.navigation.addListener( // 'didBlur', // (obj)=>{ //这里写方法 // } // ) //添加监听,显示的方法 this.viewDidAppear = this.props.navigation.addListener( 'didFocus', (obj)=>{ //这里写方法 } ) }复制代码
导航栏配置
tabBarPosition:设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:'top','bottom') swipeEnabled:是否允许在标签之间进行滑动 animationEnabled:是否在更改标签时显示动画 lazy:是否根据需要懒惰呈现标签,而不是提前,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐为true trueinitialRouteName: 设置默认的页面组件 backBehavior:按 back 键是否跳转到第一个Tab(首页), none 为不跳转 tabBarOptions:配置标签栏的一些属性iOS属性{ activeTintColor:label和icon的前景色 活跃状态下 activeBackgroundColor:label和icon的背景色 活跃状态下 inactiveTintColor:label和icon的前景色 不活跃状态下 inactiveBackgroundColor:label和icon的背景色 不活跃状态下 showLabel:是否显示label,默认开启 style:tabbar的样式 labelStyle:label的样式安卓属性 showIcon:是否显示图标,默认关闭 pressColor:material涟漪效果的颜色(安卓版本需要大于5.0) pressOpacity:按压标签的透明度变化(安卓版本需要小于5.0) scrollEnabled:是否启用可滚动选项卡 tabStyle:tab的样式 indicatorStyle:标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height设置为0来暂时解决这个问题 iconStyle:图标样式}复制代码
10.Platform 作用
如果有两个文件
BigButton.ios.jsBigButton.android.js复制代码
只需要导入 import BigButton from './components/BigButton';
然后调用 Platform 的方法即可。
11. 网上模拟器
12.修改iOS的版本
不只是改工程的版本,还要修改工程里Libraries文件夹下所有.xcodeproj的版本
13.字符串获取首位
根据例子:
const [a, b, c, d, e] = 'hello';a // "h"b // "e"c // "l"d // "l"e // "o"复制代码
字符串长度:
let {length : len} = 'hello';len // 5复制代码
交换变量的值:
let x = 1;let y = 2;[x, y] = [y, x];复制代码
判断是否创建:
typeof y === 'undefined'
强制显示小数点后两位:
scaleDecimal(x){ var f = parseFloat(x); if (isNaN(f)) { return false; } var f = Math.round(x*100)/100; var s = f.toString(); var rs = s.indexOf('.'); if (rs < 0) { rs = s.length; s += '.'; } while (s.length <= rs + 2) { s += '0'; } return s; }复制代码
将小数跟整数分开:
// 取小数 var b = a.split(".");//a 必须是字符串,呵呵 var x=b[0]; var y=b[1];复制代码
判断是否包含中文:
isChinese(str){ if(/.*[\u4e00-\u9fa5]+.*/.test(str)){ return true; }else{ return false; } }复制代码
判断字符串是否包含特定字符:
复制代码
14.函数
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
function example() { return [1, 2, 3];}let [a, b, c] = example();// 返回一个对象function example() { return { foo: 1, bar: 2 };}let { foo, bar } = example();复制代码
解构赋值对提取 JSON 对象中的数据,尤其有用。
let jsonData = { id: 42, status: "OK", data: [867, 5309]};let { id, status, data: number } = jsonData;console.log(id, status, number);复制代码
箭头函数:
var f = v => v;// 等同于var f = function (v) { return v;};复制代码
var f = () => 5;// 等同于var f = function () { return 5 };var sum = (num1, num2) => num1 + num2;// 等同于var sum = function(num1, num2) { return num1 + num2;};复制代码
2.数组的遍历 for in
方法跟 oc 不一样,遍历出来的是数组下标; for of
方法才是遍历出来数组内对象
3.获取数组内最大值
var arr = [1, 2, 3];var max = Math.max(...arr);复制代码
导航跳转 demo
1.使用系统的导航栏,导入:
yarn add react-navigation
2.在用到的任何界面都要导入:
import { createStackNavigator } from 'react-navigation';
3.在当前项目创建名为 js
文件夹,名字任意取,并创建两个 js
文件,分别为 NavigationPage.js
,NavigationPageNext.js
,
4.在 app.js
导入两个文件:
import NavigationPage from './js/NavigationPage';import NavigationPageNext from './js/NavigationPageNext';复制代码
5.在 app.js
配置导航信息:
const RootStack = createStackNavigator( { // 定义路由页面 Home: NavigationPage, homeNext: NavigationPageNext, }, { // 初始化首页 initialRouteName: 'Home', } );复制代码
6.在 app.js
的Component
方法写入:
return <RootStack />;
,这样在运行程序的时候,就会默认显示 NavigationPage
界面信息
7.在 NavigationPage.js
内写
export default class Navigation extends Component { render() { return (Welcome to React Native!
这个时候可能会报错,导入系统的 Button 组件:
import { Button } from 'react-native';
8.在 NavigationPageNext
界面增加一个返回按钮:
return (Welcome to React Native!
这样就完成了~
动态计算视图高度
有时候因为文本内容不固定,所以在创建组件时不会给确切的高度,比如文本(Text)高度,视图(View)高度,列表(Flatlist)高度。很多时候我们可能不会去计算组件的动态高度,因为即使不给固定的高度,组件也能够自适应的显示该有的东西,但是在涉及到多个不确定高度的组件捆绑在一个组件中时,我们就可能要用到这个属性。
每每个组件都可以设置 onLayout 属性来获取组件的位置信息,这个方法便是在组件加载时获取高度的属性。
例如计算 Flatlist 高度,先在 constructor 中初始化高度,
constructor(props){ super(props); this.state={ recordCellHeight:0, }; }复制代码
定义一个实现计算高度的方法
landCellLayout(event){ var width = event.nativeEvent.layout.width, var height = event.nativeEvent.layout.height, this.setState({ recordCellHeight:height }) }复制代码
event 为当前绑定视图的顶级对象,layout属性便是该视图的布局属性,从里面可以获取到对应的视图宽度跟高度。
赋值给组件,
复制代码
在 style 里先给组件高度,然后在 onLayout 里对高度进行重新赋值,需要注意的是要在 this.setState 这个方法里进行数据操作,这样相关视图会得到重新渲染的机会。
另外,也可以不用定义方法,在 onLayout里写方法也是可以的。
{ this.setState({ recordCellHeight:e.nativeEvent.layout.height })} />复制代码
这是计算单个视图的高度方法,向上面所说,如果在一个组件中包含多个组件,并且取高度最大组件的值,可以写一个比较方法来实现。假设组件 A 跟 B,高度分别为 A.height ,B.height。在获取高度的方法中,调用比较方法
Layout(event){ this.getMaxHeight(A.height,B.height); }复制代码
再接着实现 getMaxHeight 方法,主要思路是利用三目运算得出值,最后通过 this.setState 方法刷新布局。
getMaxHeight(x,y){ var max = x > y?x:y, this.setState({ max:max })}复制代码
使用 RNFS
拷贝文件:
RNFS.copyFile(uri,imageUrl) .then(()=>{ console.log('copy成功~') DeviceEventEmitter.emit('editPic',{height:self.state.linelength,startDepth:self.state.lineNum,imageUrl:imageUrl, imageWidth:self.state.imageCom.width,imageHeight:self.state.imageCom.height }); self.props.navigation.goBack(self.state.keys.A_key); }) .catch((error)=>{ console.log('copyd~',error) });复制代码
注意 imageurl 路径里包含图片名称
使用 react-navagation 跳转指定界面
关键:this.props.navigation.state.key
安装部分三方库出现的问题
以下说的操作路径均是打开Android Studio下 1.安装 react-native-image-picker
的时候,出现 Error: react-native-image-picker:processReleaseResources
第一种解决方案: 在 androi/app/Gradle Scripts
下面,找到 build.gradle(Module.app),在底部增加这么一句话
subprojects { afterEvaluate {project -> if (project.hasProperty("android")) { android { compileSdkVersion 26 // <-- match this to your project's compileSdkVersion buildToolsVersion '26.0.3' // <-- match this to your project's buildToolsVersion } } } }
第二种方案:直接在那个库里修改
compileSdkVersion 26 // <-- match this to your project's compileSdkVersionbuildToolsVersion '26.0.3' 复制代码
2.安装二维码扫描三方库 ac-qrcode
运行出现的问题
第一个问题: > Could not find method google() for arguments [] on repository container.
解决方法:在 androi/app/Gradle Scripts
下面,找到 build.gradle(Project:项目名)
,将 classpath 里的版本改成 3.0.1
接着会碰到第二个问题:
Error:Minimum supported Gradle version is 4.1. Current version is 2.14.1. If using the gradle wrap复制代码
查看一下gradle-wrapper.properties下面的distributionUrl改成它说的最小的 4.1
3.安装 realm 后存储数据
问题1:constructro must be of type 'function',got(undefined)
版本为 realm:2.18.0, RN :0.56.0
解决方法:回退版本到 2.16.0(注意,不是 ^2.16.0),
终端运行:watchman watch-del-all rm -rf TMPDIR/metro-bundler-cache-* rm -rf node_modules/ yarn cache clean yarn install yarn start -- --reset-cache
爆红问题归纳
1.
Invariant Violation: Element type is invalid: expected a string( for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in复制代码
如果在导入组件时,是这样导入的话: import a from './a'
1.需要按照类似这样写:
import { AppRegistry } from 'react-native';import Header from './src/components/header';//Create a Componentconst App = () => ();//Export App - This line solved my issueexport default App;//Render it to the deviceAppRegistry.registerComponent('albums', () => App);//albums is project name that we use while creating RN App复制代码
2.最简单方法是在导入时这样: import {a} from './a'
加个括号即可
2.
attempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.drawable$constantstate.newdrawable(android.content.res.resources)' on a null object reference'复制代码
原因:在 Flatlist 组件内包含 TextInput ,并且只在安卓上出现 解决方法:进入 android/app/src/main/res/values/styles.xml
文件内,在这里面把 + 号的内容添加上即可
复制代码
3.网络请求成功后没有回调
在 fecth 内走成功的方法中不能用 alert,不然方法会被打断
4.
node_modules/react-native/libraries/animated/src/nodes/animatednode.js:enoent:no such file or directory,uv_cwd(null)复制代码
原因:缓存问题,且是在iOS上出现 解决方案:关闭本地服务器,运行:react-native start --reset-cache
5.
Module `***` does not exist in the Haste module map复制代码
解决方案:npm start -- --reset-cache
6.
Build input file cannot be found: '/Users/me/Desktop/路径/路径/项目/node_modules/react-native/third-party/double-conversion-1.1.5/src/strtod.cc'复制代码
原因:只在 Xcode 上出现
解决方案:
-
第一种方法:终端运行
sed -i '' '/DevelopmentTeam = V9WTTPBFK9/d;/DEVELOPMENT_TEAM/d;/ProvisioningStyle = Automatic/d' ./node_modules/react-native/React/React.xcodeproj/project.pbxproj
-
第二种方法,依次执行两条命令:
-
cd node_modules/react-native/scripts && ./ios-install-third-party.sh && cd ../../../
-
cd node_modules/react-native/third-party/glog-0.3.5/ && ../../scripts/ios-configure-glog.sh && cd ../../../../
-
7.安卓网络请求失败或者图片加载不出来
尝试使用模拟器的浏览器打开网站,打不开的话模拟器连一下wifi~即可
8.
Could not invoke ImagePickerManager.showImagePicker on Android复制代码
这是网络上别人提供的方法:
updating to support-v4 and appcompat-v7 helps me:com.android.support:appcompat-v7:27.1.1com.android.support:support-v4:27.1.1复制代码
9.Cocopoads安装三方问题
If cocoapods is used and if error RNSVGImage.m:12:9: 'React/RCTImageLoader.h' file not found occurs:
Add the following entry in Podfile:
pod 'React', :path => '../node_modules/react-native', :subspecs => [ [...] 'RCTImage', # !!!!!]复制代码
从网页点击跳转到指定 APP
1.iOS 端的实现
1.打开 Xcode,选择工程,然后点击 Info 一栏,点击 URL Types,
2.点击 + 号并新增一个 url,只需要在 URL Schemes 中添加一串内容即可。
比如添加的内容是 :luweisurvey
3.然后我们安装 app,在 safari 上输入 luweisurvey:// 就会弹出跳转的提示了
2.安卓端的实现
1.进入 AndroidManifest.xml 文件,具体路径为:android->app->AndroidManifest.xml,
2.找到 activity 标签,添加以下标签内容:
复制代码
3.根据实际情况修改一下 <data android:scheme="luweisurvey" />
里的schme内容
4.在安卓手机上,打开浏览器,scheme 内容是什么就输入什么,这里用的是 luweisurvey,那就是输入 luweisurvey:// ,但是这个时候是没有办法跳转的,因为浏览器默认搜索功能,点击搜索就会出来一大堆搜索结果~~。这个时候我们如果需要自己做测试的话,可以写一个网页点击按钮实现跳转到 luweisurvey:// 来实现。
5.随便用一个工具打开一个文本,输入:
测试一下
Click 复制代码
保存,格式为 html,然后放到网上,这个怎么操作大家应该都知道~~。
6.然后在手机上点击网页按钮测试成功~
注意的地方
1.如果网页端点击跳转失败,那有可能是因为跳转链接是 luweisurvey 而不是 luweisurvey:// 2.跳转功能已经可以满足大部分的业务需求,以后再更新跳转到指定界面的攻略~
键盘监听
键盘监听作用是为了在键盘弹起时遮挡了我们想要看到或者输入的内容,对于常规业务的实现来说,我们只需要监听键盘已经出现,以及键盘已经消失就可以了。
具体监听的使用方法也很简单,只有几行代码:
1.创建监听
componentWillMount() { //监听键盘弹出事件 this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShowHandler.bind(this)); //监听键盘隐藏事件 this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHideHandler.bind(this)) }复制代码
2.实现监听的方法
//键盘弹出事件响应 keyboardDidShowHandler(event) { //... } //键盘隐藏事件响应 keyboardDidHideHandler(event) { //... }复制代码
其中 event 里面包含的内容如下:
{ easing: 'keyboard', duration: 250, endCoordinates:{ height: 304,键盘高度 screenX: 0, x轴坐标 width: 375,键盘宽度 screenY: 363 y轴坐标 }, startCoordinates: { height: 304, screenX: 0, width: 375, screenY: 667 } }复制代码
startCoordinates 是键盘即将弹出时的位置信息,endCoordinates 是键盘已经弹出的位置信息
其实像 textinput 输入框这样的控件,iOS 端使用 IQKeyboardManager,安卓端配置一下文件,是可以实现避免遮盖输入框问题的,不过有些时候,我们不只是需要避免这个,而是还要把输入框下的按钮也能显示出来,这样的话,我们就只能自己动手来实现了。
具体思路是这样的: 1.控件都是写在 scrolleview 上 2.键盘弹起时,获取到键盘当前位置,以及控件的位置,并判断是否出现遮挡 3.遮挡的话,把 scrolleview 的 marginTop 改变一下 4.结束输入时,也就是键盘隐藏后,恢复 scrolleview 的 marginTop的值
获取控件的位置
说到这里应该都知道该怎么做了,现在来教一下怎么获取控件的位置。
倒入必要的系统组件
import { Keyboard,findNodeHandle } from 'NativeModules';import { UIManager } from 'react-native';复制代码
在对应组件中使用:
{ this.progressBar = c }} onLayout={() => { const handle = findNodeHandle(this.progressBar); setTimeout(()=>{UIManager.measure(handle, (x, y, width, height, pageX, pageY) => { console.warn(x, y, width, height, pageX, pageY) // 0, 0, 315, 63, 32, 396.5})},1000) }} />复制代码
开发结束
1.studio 安装 apk 到手机
installation failed with message failed to finalize session:install_failed_i复制代码
在 build.gradle 里写:
splits { abi {// reset()// enable enableSeparateBuildPerCPUArchitecture// universalApk false // If true, also generate a universal APK// include "armeabi-v7a", "x86" enable true reset() include 'x86', 'armeabi-v7a' universalApk true } }复制代码
2.移动了安卓文件
把 android 文件夹下的 .gradle,.idea 跟 build 文件夹删掉重新编译
3.安卓图标
只需要放在 :
android/app/src/main/res/mipmap-xhdpi/ic_app_icon.png
同时图片一定要保证是 png,如果不是,不能直接改名,而是先导出为 png,没有后缀的时候再添加一个 png 的后缀
4.安卓打包路径
默认路径 release 包:../android/app/build/outputs/apk/release/app-release.apk
5.打包 iOS 方法:
- 因为react-native 时使用 react-native bundle来进行打包,打包命令为:
"bundle-ios":"node node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform ios --dev false --bundle-output ./ios/bundle/index.ios.jsbundle --assets-dest ./ios/bundle"
因此我们现在 npm脚本内写好打包的命令,也就是快捷键 - 首先在项目内的 package内,找到 "script",将命令添加保存
- 在终端运行npm命令 :npm run bundle-ios
- 这个时候可能会出现 :
* Exploration@0.0.1 bundle-ios: `node node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform ios --dev false --bundle-output ./ios/bundle/index.ios.jsbundle --assets-dest ./ios/bundle` 复制代码
这个时候不用慌,打开对应路径上的 index.js ,然后修改这个语句: export default class { ... }
-> default class Chicken { .. }
或者改成 export default class Chicken{ .. }
- 接着重新 npm run bundle-ios
- 在appdelegate里配置一下bundle:
//开发包// jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; //离线包 jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"bundle/index.ios" withExtension:@"jsbundle"];复制代码
6.安卓打包
1.react-native bundle --entry-file index.js --platform android --dev false --bundle-output ./android/app/src/main/assets/index.bundle --assets-dest ./android/app/src/main/res/
2.配置必要证书(jsk)
3.cd android && ./gradlew assembleRelease
问题:
- 如果出现:
error: Duplicate file. Original is here. The version qualifier may be implied
则使用这句命令
rm -rf android/app/src/main/res/drawable-xxxhdpi android/app/src/main/res/drawable-xxhdpi android/app/src/main/res/drawable-xhdpi android/app/src/main/res/drawable-mdpi android/app/src/main/res/drawable-hdpi
重新执行 ./gradlew assembleRelease
- 出现:`Execution failed for task ':app:lintVitalRelease'.
java.lang.NullPointerException (no error message)`
在 build.gradle 里添加
lintOptions { checkReleaseBuilds false }
node_modules/react-native/third-party/glog-0.3.4/test-driver'. Couldn't follow symbolic link.
第一种解决方法:unlink node_modules/react-native/third-party/glog-0.3.4/test-driver
第二种解决方法:
watchman watch-del-allrm -rf node_modulesrm -rf $TMPDIR/react-*npm install react-native link复制代码
安卓: 清除缓存:cd android && ./gradlew clean
插件
React Native Snippet
RN的css提示
待解决问题
1.使用DeviceEventEmitter监听,会出现走两次接收的方法 2.怎么判断按钮点击取消?
这是笔者日常开发中记录的笔记,希望能给到一同在 React-Native 开发路上的道友们提供自己的力量?