Props(属性)
大多数组件在创建时就可以使用各种参数来进行定制。用于定制的这些参数就称为props。
以常见的基础组件Image为例,在创建一个图片时,可以传入一个名为source的prop来指定要显示的图片的地址,以及使用名为style的prop来控制其尺寸。
import React, { Component } from 'react';
import { AppRegistry, Image } from 'react-native';
class Bananas extends Component {
render() {
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};
return (
<Image source={pic} style={{width: 193, height: 110}} />
);
}
}
AppRegistry.registerComponent('Bananas', () => Bananas);
注意到{pic}外围有一层括号,我们需要来把pic这个变量嵌入到JSX语句中。括号的意思是括号内部为一个js变量或表达式,需要执行后取值。因此我们可以把任意合法的JavaScript表法师通过括号嵌入到JSX语句中。自定义组件也可以使用props。通过在不同的属性定制,可以尽量提高自定义组件的复用范畴。只需在render函数中引用this.props,然后按需处理即可。
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);
上面的列子中,我们在Greeting组件中将name作为一个属性来定制,这样可以复用这一组件来制作各种不同的‘问候语’。上面的列子把Greeting组件写在JSX语句中,用法和内置组件并无二致—这正是React体系的魅力所在---
State(状态)
我们使用两种数据来控制一个组件:props和state。props是在父组件中指定,而且已经指定,在被指定的组件的生命周期中则不再改变。对于需要改变的数据,我们需要使用state。
一般来说,你需要在constructor中初始化state(这是ES6的写法),然后在需要修改时调用setState方法。
假如需要制作一段不停闪烁的文字。文字的内容本身在组件创建时就已经指定好了,所以文字内容应该是一个prop。而文字的显示或隐藏的状态(快速的显隐切换就产生了闪烁的效果)则是随着时间变化的,因此这一状态应该写在state中。
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Blink extends Component {
constructor(props) {
super(props);
this.state = { showText: true };
// 每1000毫秒对showText状态做一次取反操作
setInterval(() => {
this.setState(previousState => {
return { showText: !previousState.showText };
});
}, 1000);
}
render() {
// 根据当前showText的值决定是否显示text内容
let display = this.state.showText ? this.props.text : ' ';
return (
<Text>{display}</Text>
);
}
}
class BlinkApp extends Component {
render() {
return (
<View>
<Blink text='I love to blink' />
<Blink text='Yes blinking is so great' />
<Blink text='Why did they ever take this out of HTML' />
<Blink text='Look at me look at me look at me' />
</View>
);
}
}
AppRegistry.registerComponent('BlinkApp', () => BlinkApp);
实际开发中,我们一般不会在定时器函数(setInterval、setTimeout等)中来操作state。典型的场景是在接收到服务器返回的新数据,或者在用户输入数据之后。你也可以使用一些“状态容器”比如Redux来统一管理数据流。
State的工作原理和React.js完全一致,所以对于处理state的一些更深入的细节,你可以参阅React.Component API。
样式
在React Native中,你并不需要学习什么特殊的语法来定义样式。我们仍然使用JavaScript来写样式。所有的核心组件都接受名为style的属性。这些样式名基本上是遵循了web上的CSS命名,只是按照JS的语法要求使用了驼峰命名法,例如将 background-color改为backgroundColor
style属性可以是一个普通的JavaScript对象,这是最简单的用法,因而在实例代码中很常见。你还可以传入一个数组 — — 在数组中位置居后的样式比居前的优先级更高,这样你可以间接实现样式的继承。
实际开发中组件的样式会越来越复杂,建议使用StyleSheet.create来集中定义组件的样式。
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
class LotsOfStyles extends Component {
render() {
return (
<View>
<Text style={styles.red}>just red</Text>
<Text style={styles.bigblue}>just bigblue</Text>
<Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
<Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigblue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
AppRegistry.registerComponent('LotsOfStyles', () => LotsOfStyles);
常见的做法是按顺序声明和使用style属性,以借鉴CSS中的“层叠”做法(即后声明的数学系会颠覆先声明的同名属性)