最近使用​​react-native​​参与开发了个应用,记录下其中踩的一些坑。本人使用的是mac电脑进行开发,本文仅对此平台进行记录📝

下载不了xcode

升级自己的mac的系统到最新版本,之后在mac的应用市场中下载xcode。

app Store -> Develop ->

请保持网络的顺畅,升级系统和下载安装​​xcode​​比较耗时,需耐心等待啦~

ran "xcodebuild" command, error code for 65

跑起来的时候可能会出现这样的错误:

error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65. To debug build logs further, consider building your app with Xcode.app, by

可以参考下面的步骤解决:

  • 用xcode当前当前项目,如​​File -> Open -> demo_native -> ios​
  • 选择​​File -> Project Setting -> Advanced -> Custom -> Relative to workspace​
  • rm -rf node_modules
  • killall -9 com.apple.CoreSimulator.CoreSimulatorService
  • sudo react-native run-ios

​react-native run-ios​​后没反应

在完成了相关的下载之后,运行react-native项目之后过两三分钟还是没有反应,请确保你的网络良好并重新运行,等待上一段时间。

首次跑应用耗时比较长,第二次跑的话就很快了~

出现​​Entry, ":CFBundleIdentifier", Does Not Exist​​错误

在执行​​react-native run-ios​​​后出现​​Entry, ":CFBundleIdentifier", Does Not Exist​​​,可以通过更改文件的设置来解决,xcode打开文件目录后,​​File -> Project Setting -> Advanced -> Custom -> Relative to workspace​​。如果还是不行,请使用好点的工具(比如使用SS,而不是蓝灯)。

最主要的还是保持网络的良好,不然相关依赖下载会失败的

实现页面的热加载

在项目启动之后,mac上的模拟器已经开启了,但是修改保存ide上的代码后,模拟器并不能够实现热加载。这个时候应该开启模拟器的项目热加载功能。做法如下:

模拟器中进入正在执行的项目,然后在mac上按住​​command + d​​​就可以调出对话框,选择​​Enable Live Reload​​就可以了。

关联浏览器调试

运行项目之后,可以在浏览器内对应用的js进行调试。调试操作:

  • 运行项目后在浏览器上打开​​http://localhost:8081/debugger-ui/​
  • 在启动的项目中开启远程js debugger。​​command+d -> Debug JS Remotely​

⚠️【开启远程调试会拖慢app的运行速度,有需要的时候再开启】

基础要点

props(属性)和state(状态)

​props​​​是在父组件中指定,在被指定的组件生命周期中不做改变。如果需要改变的数据,则可以使用​​state​​。

this的绑定

ES6中自定义的函数里面使用​​this​​​关键字,需要对其进行绑定操纵,否则​​this​​的指向会指向空。操作示例:

...
constructor(props) {
super(props);
this.state = {
data: [],
loaded: false
},
this.fetchData = this.fetchData.bind(this);
}
fecthData() {
fetch(REQUEST_URL){
this.setState({
data: this.state.data.concat(['name'])
})
}
}

样式编写的几种方式

1. 使用类名

// 单个类名
<View style = { styles.container }>
<Text>some awesome text</Text>
</View>

const styles = StyleSheet.create({
container: {
backgroundColor: '#f8f8f8',
flex: 1
}
})

// 多个类名
<View style = { [styles.container, styles.colorRed]}>
<Text>some awesome text</Text>
</View>

const styles = StyleSheet.create({
container: {
backgroundColor: '#f8f8f8',
flex: 1
},
colorRed: {
color: '#f00'

2. 使用行内样式

<View style = {{ backgroundColor: '#f8f8f8', flex: 1
<Text>some awesome text</Text>
</View>

3. 类名和行内样式结合

<View style = { [styles.container, { color: '#f00' }] }>
<Text>some awesome text</Text>
</View>

const styles = StyleSheet.create({
container: {
backgroundColor: '#f8f8f8',

父子组件的传值

这里没有引入状态管理工具,比如redux。

1. 父组件传值给子组件

通过props进行值的传递

// 父组件
import Child from 'path/to/Child'

<View>
<Child name='jiaming'/>
</View>

// 子组件
render() {
const { name } = this.props;
return(
<View>
<Text> { name } </text>
</View>

2. 子组件传值给父组件

通过props的方法进行传值

// 父组件
import Child from 'path/to/Child'

getValue(data) {
console.log(data);
}

render() {
return (
<View>
<Child getValue = { this.getValue.bind() }>
</View>
)
}

// 子组件
trigger() {
this.props.getValue({
name: 'name from child component'
});
}
render() {
return (
<View>
<Text onPress={ this.trigger.bind(this) }> some awesome text </Text>
</View>

父组件的数据状态变动,子组件的数据没变动?

在父组件中设置了父组件的数据变动了,但是子组件的数据并没有变动。比如:

// 父组件
import Child from 'path/to/Child'

Fn() {
this.setState({
name: 'jiaming'
});
}

<View>
<Child name = { this.state.name
</View>

出现在子组件中数据没变动的话,应该在子组件中做下面的处理:

  • 在componentWillReceiveProps钩子内处理
  • componentWillReceiveProps钩子函数上传入props参数代替函数内的this.props

相关的案例如下:

componentWillReceiveProps(props) { // props这个参数要加上
const {
name
} = props; // 这里不能使用this.props,不然会造成数据渲染不同步
this.setState({
name: name
});
}

setState中引入变量

在我们改变state值的时候,我们一般都会使用到​​setState​​,比如:

constructor(props){
super(props);
this.state = {
name : ''
}
}

Fn() {
this.setState({
name: 'jiaming'

上面的​​setState​​中的key值是name,那么,如果我使用一个变量代替name需要怎么写呢?

答:使用中括号​​[]​​来包裹就行了。如下demo

Fn() {
const _name = 'jiaming';
this.setState({
[_name]: 'jiaming'

​render return​​内的条件判断写法

在​​View​​​页面内,很多时候是需要你根据条件判断进行,那么相关的写法你可以包裹在一个大括号​​{}​​里面的。比如:

constructor(props){
super(props);
this.state = {
typeFlag: 1
}
}
render() {
return (
<View>
{
typeFlag == 1 ?
<Text>type flag is one</Text>
:
typeFlag == 2 ?
<Text>type flag is two</Text>
:
null
}
</View>

使用Modal会遮住下层的内容

在开始时候,引入​​Modal​​​之后是,执行了相关的代码,弹出了​​Modal​​​之后,是看不到下层的内容的,这很是不合理。解决方案:引入属性​​transparent​​。

如下:

render() {
return (
<Modal
animationType='slide'
transparent='true'>
<View>
<Text>some awesome text</Text>
</View>
</Modal>

javascript的引入方式

1. 行内编写

<TouchableOpacity onPress={ () => console.log('this is a demo')}>
<Text>some awesome text</Text>
</TouchableOpacity>

2. 行内引入指针

handleEvent() {
console.log('this is a demo');
}

<TouchableOpacity onPress={ this.handleEvent.bind(this) }>
<Text>some awesome text</Text>
</TouchableOpacity>

navigation内的事件编写

在​​react native navigation​​​中直接使用类似​​this.handleMethod​​这种方法是不生效的,比如:

static navigationOptions = ({navigation}) => ({
headerLeft: (
<TouchableOpacity onPress = { this.handleMothed.bind(this) }>
<Text style={{ color: '#999', paddingLeft: 10}}>返回</Text>
</TouchableOpacity>
)
});
handleMothed(){
console.log('this is a demo');
}

你应该这样写(使用​​this.props.navigation.setParams​​):

static navigationOptions = ({navigation}) => ({
headerRight: (
<TouchableOpacity onPress= {()=>navigation.state.params.handleComfirm()} >
<Text style={{ color: '#999', paddingLeft: 10}}>确认</Text>
</TouchableOpacity>
)
)
});

componentDidMount() {
// 组件加载完之后操作
this.props.navigation.setParams({handleComfirm:this.handleComfirm})
}

handleComfirm() {
console.log('this is a demo');
}

mac上安装的安卓adb

使用brew安装。

- 默认已经安装了brew
- brew cask install android-platform-tools // Install adb
- adb devices // Start using adb

⚠️在安装的过程中,请保持网络的顺畅。

参考链接:www.jianshu.com/p/bb74ae9d2…

后话

文章部分内容的引用已丢失,若有雷同,不胜荣幸。如有错误,还望看官纠正。

更多的内容请前往我的博客