- 因为RN版本更新频繁,所以后期每次新建一个工程的时候,都会报类似
unmet peer dependency
的警告,说RN的版本不符合之类的。找了stack over flow和github上面的很多资料,没有招到相应的解决方案。暂时先不管了。因为似乎不影响使用。只是不知道后续会不会需要指定版本来创建项目 - 如果要修改项目存放的地址,记住,这个项目的父路径不能包含空格或特殊字符,否则Xcode中无法编译通过。这是今天碰到最大的坑。
2017.8.4
知识点
- state状态机的概念
在一个类初始化时,在构造函数中必须定义的变量.
- 箭头函数的理解
=>
简单的理解,箭头函数也可以看做一个简单的匿名函数。- 函数的左边是参数,右边是表达式,可以看做
() => {return something}
. - 如果参数为空,用
()
表示.否则可以用(param1,param2) => {return param1,param2,'3'}
- 左边的参数可以和右边毫不相关(但是这样没什么意义,如果 不相关,那直接就传空参数就好了)
- 有时候,右侧的表达式是一个函数,例如
() => this.someFunction
,虽然这样写不会报错,个人感觉目前为初学阶段,统一右侧加上表达式,改写为
() => {return this.someFunction;}
或
() => {this.someFunction;}
- 函数的左边是参数,右边是表达式,可以看做
回调的机制 —— 包括如何切换状态机
先说如何切换状态机.指的是在需要的时机,改变this.state
中某个变量的值。以下面的代码为例,修改的就是inputNum
和inputPW
this.state = {inputNum: '',
inputPW: '',};
修改状态机
- 必须调用
this.setState
方法 -
setState
参数必须是一个函数变量(可以查看他的函数原型参数),我们这里通常使用箭头函数来传值
this.setState(
() = {return {inputNum:'neededValue',}}
);
下面是一个示例代码
以我们目前看到的textInput
为例来说明
export default class LoginDemo extends Component {
constructor(props) {
super(props);
this.state = {
inputNum: '',
inputPW: '',
};
this.updatePW = this.updatePW.bind(this);
}
updateNum(newText) {
console.log("设置数字,输入" + newText);
this.setState(
() => {return {inputNum:newText,}}
);
}
updatePW(newText) {
console.log("设置密码,输入" + newText);
this.setState()
}
render() {
return (
<View style={styles.container}>
<TextInput style={styles.inputStyle}
selectionColor={'red'}
placeholder={"请输入数字\n"}
placeholderTextColor={'purple'}
onChangeText={
(a) => {this.updateNum(a);}
}
/>
<Text style={styles.welcome}>
您输入的电话号码 : {this.state.inputNum}
</Text>
<Text style={styles.welcome}>
您输入的密码 : {this.state.inputPW}
</Text>
<TextInput style={styles.inputStyle}
maxLength={6}
placeholder={"请输入密码\n"}
secureTextEntry={true}
onChangeText={(newText) => this.updatePW(newText)}
/>
</View>
);
}
}
代码实现的目的是在 TextInput
中输入字符串,同时通过监听函数onChangeText
去更新另一个Text
的显示值.
- 这里就涉及到了,我改变了状态机变量
inputNum
,如何使他生效的问题。
修改inputNum
要调用到设置状态机的函数方法.this.setState(() => {return {inputNum:'something'}})
根据书上的理论,修改状态机,虽然从JS
的代码上来说,通过this.state = someValue
是可行的,但是RN
中并不能识别这种赋值方式。 - 回调函数
onChangeText
的参数是一个函数变量。这里就带来了一个问题—— {}中放的究竟是怎么样的函数,才算合适?-
onChangeText={this.updateNum}
—— 直接传递函数。
理论上似乎可行,书中写的也是说可行的。但是实际运行的时候会报错,
-
从报错的原因来看,应该是onChangeText
要求{}中传递的参数是一个函数,但是实际上,调用 this.updateNum
的时候,他是将this.setState
的执行结果返回了。
-
onChangeText={this.updateNum(newText)}
这种方式不用讨论,肯定不行。首先newText
未定义,其次就算newText是一个已知数,那么执行的结果仍然不是一个函数。
如果将newText换成一个具体的字符串'string'
,执行的结果会造成死循环. - 从上一点来看,如何将一个带形参的函数传递进去,变成了应该要解决的问题。因此就要用到箭头函数
onChangeText={(a) => {this.updateNum(a);}}
真机调试
鉴于上面的介绍,我在两个平台调试时,并不以 react-native run-ios
或react-native run-android
命令来运行,而是分别使用Xcode
和Android Studio
来做。
Xcode
没什么好说了,但是安卓的真机调试有一个坑。
真机调试首次加载可能会报错:
java.lang.RuntimeException: Unable to load script from assets 'index.android.bundle'. Make sure your bundle is packaged correctly or you're running a packager server.
这是因为还没有在手机上设置 server 和 port,摇一摇启动设置页面,点击 DevSettings -> Debug server host & port for device -> 输入 [本机ip]:8081,本机 ip 可用 ifconfig 命令查看。输入完后返回,再摇一摇然后点击 Reload 即可。