前言
这篇文章来介绍一下RN的属性和状态,以及在之前Hello World项目中已经出现的比如style等UI样式的使用,之后我们就能使用这些来搭建一些简单的UI界面。
还记得搭建环境的时候init的AwesomeProject项目吧,我们把它导入到WebStorm中,下边的内容都可以在里边改代码!
关于如何运行,可以查看上一篇博客,这里就不赘述了!
Props(属性)
大多数组件在创建时就可以使用各种参数来进行定制。用于定制的这些参数就称为props(属性)。
我们还是来对比Android中的属性,比如TextView,常见的width
,height
,text
,padding
等等,ImageView的src
,scaleType
等,这些就是这些控件的属性。
那么同样的对于RN中的组件来说,它也有一系列与之对应的属性,只不过写法上有些不同罢了!
这里我们举个例子,以RN中的Image
,对应Android中的ImageView,Image
是用来展示图片的组件。
那我们要用Image这个组件,首先就需要导入进来:
import {
AppRegistry,Image,StyleSheet,Text,View
} from 'react-native';
我们在项目中将Image添加进来,之后就可以使用这个组件了!
我们在网上随便找来一张图片!然后将render(){}
方法中的内容改为:
let pic={ uri: 'http://p4.music.126.net/cq1STvQ6q5b_Eg5grsTjYQ==/3275445147663993.jpg' }; //加载网络图片,必须指定图片尺寸 return ( <View style={styles.container}> <Image source={pic} style={{width: 200,height: 200}} /> <Text style={styles.welcome}>This is a picture of Taylor Swift</Text> </View> );
然后我们运行一下,看一下效果!
代码中<Image source={pic} style={{width: 200,height: 200}} />
的source
就是组件Image的属性,指定要显示的图片的地址,这个属性很类似ImageView的src属性。
需要注意的一点:{pic}
外围有一层括号,我们需要用括号来把pic这个变量嵌入到JSX语句中。括号的意思是括号内部为一个js变量或表达式,需要执行后取值。因此我们可以把任意合法的JavaScript表达式通过括号嵌入到JSX语句中。
跟我们直接把地址放进去是一样的:
<Image source={{uri: 'http://p4.music.126.net/cq1STvQ6q5b_Eg5grsTjYQ==/3275445147663993.jpg'}} style={{width: 200,height: 200}} />
另外就是,Image组件在加载网络图片的时候,必须要指定宽高,这个先记着就行,关于图片我们之后再做讨论!
还有就是代码中let pic={...};
的let
是ES6新增的命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let命令所在的代码块内有效。
前边提到的import
,class
,const
都是ES6**新增的用于声明变量的命令**,加上ES5中已经有的var
,function
,共有6种声明不同变量的命令!
样式style
这里style也是Image的属性,而且几乎全部的组件都有style这个属性,这里主要用来设置宽高,而且是直接在里边写了{width: 200,height: 200}
,但是我们还记得这个项目里边,
const styles = StyleSheet.create({ container: { flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},welcome: { fontSize: 20,textAlign: 'center',margin: 10,instructions: { textAlign: 'center',color: '#333333',marginBottom: 5,});
在外边声明style,然后再去引用是一样的。
从这个层面上看,style更像是一个属性的集合,里边是一个个的属性,我们把需要设置的属性放在里边,然后一句话去引用。这跟Android里边的style是非常类似的!
关于style,这些样式名基本上是遵循了web上的CSS的命名,只是按照JS的语法要求使用了驼峰命名法,例如将background-color
改为backgroundColor
style属性可以是一个普通的JavaScript对象。这是最简单的用法,就像示例项目中那样。还可以传入一个数组——在数组中位置居后的样式对象比居前的优先级更高,这样你可以间接实现样式的继承。
比如:
<Text style={[styles.container,styles.instructions]}>
重点:后声明的属性会覆盖先声明的同名属性。
就是如果container和instructions,如果有同名的属性,那么instructions中的该属性会起作用,而container中的该属性则无效!
自定义组件的属性
我们在前一篇博客中说过,可以extents Component
来自定义组件,自定义的组件也可以使用props
,通过在不同的场景使用不同的属性定制,可以尽量提高自定义组件的复用范畴。只需在render函数中引用this.props
,然后按需处理即可。
比如说我们不是这一张图片,是好多明星的图片,那我们在描述这张图片的时候,如果还是写一个个的<Text/>
来说This is a picture of xxxx,那也太low了!所以,我们可以将下边的描述单独抽离出来成一个组件,而且将明星名字作为一个属性,就可以复用了!
自定义一个组件:
class Description extends Component{
render() {
return (
<Text style={styles.welcome}>This is a picture of {this.props.name}</Text>
);
}
}
然后这样用:
return ( <View style={styles.container}> <Image source={pic} style={{width: 200,height: 200}} /> <Description name="Taylor Swift"/> </View> );
这里的name
就是我们自定义组件Description的一个属性,当然你可以用其他的词,只要用的时候写一样的就OK!
重新reload一下,发现运行效果是一样的!
State(状态)
这里借助官网的说明:
我们使用两种数据来控制一个组件:props
和state
。props
是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变。 对于需要改变的数据,我们需要使用state
。
一般来说,你需要在constructor中初始化state
(译注:这是ES6的写法,早期的很多ES5的例子使用的是getInitialState方法来初始化state,这一做法会逐渐被淘汰),然后在需要修改时调用setState
方法。
通过上面的描述,我们发现思路呢和java代码很类似啊,constructor顾名思义构造器,在构造器中给state初始化一个值,然后如果需要修改,就调用setState
方法,也很好理解!
这里给出官方例子,不过我们还在Description中写:
class Description 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 text="This is a picture of " + this.props.name;
let display = this.state.showText ? text : ' ';
return (
<Text>{display}</Text>
);
}
}
reload一下,就可以看见这些字一闪一闪的了!
需要注意的地方:
setInterval
,setTimeout
等是定时器函数,这些之后会作了解!
如官网所说,我们一般不会在定时器函数(setInterval、setTimeout等)中来操作state,典型的场景是在接收到服务器返回的新数据,或者在用户输入数据之后。
同样的对比Android,这里相当于模拟网络请求数据,然后延时1s,去改变UI状态!这样是不是好理解多了!
更高端一点的,可以使用一些“状态容器”比如Redux来统一管理数据流,这个以后再去慢慢了解!
结语
本篇文章过后,我们就了解了组件的属性和状态,以及为组件设置样式style,包括自定义组件。这样我们能够基本编写出一些简单的UI界面了! 好了,先这样了,下篇再见!