属性(props)
在React Native中属性不会像android、java那样进行声明!我们需要什么属性直接进行在适当时候使用即可,在组件初始化,或者某种触发条件下进行相关属性赋值。例如:我们自定义一个Component为Greeting,然后外界传递一个name属性,在Greeting进行渲染View(调用render())时候使用name属性显示内容,代码如下:
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
接下来,我们只要在我们需要使用到Greeting的时候进行初始化传入name
<Greeting name='Rexxar' />
state (状态机)
在React Native中state是非常重要的一个概念,也正是因此React Native的组件化,或者叫静态化成为可能。可以将这个理解成面向对象中的封装,我们实现一个组件专门完成一项功能,在不同条件下进行相应的变化,如果将这个变化过程进行封装起来成一个模块,那么问题来了,这个条件如何从外界传入,组件如何触发这个条件的变化!
没错!state就是完成这个任务的!
我们来实现一个案例:
1、我们实现一个每2秒钟就递增1的组件
2、初始化时候传入开始数值count
class CountText extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {count: this.props.count};
//每个2秒钟修改一次count
setInterval(() => {
this.setState(c => {
return {count: c.count + 1};
});
}, 2000);
}
render() {
return (
<Text>{this.state.count}</Text>
);
}
}
export default class App extends Component<{}> {
render() {
return (
<View style={styles.container}>
<CountText count={3}/>
</View>
);
}
}
注意一下在这里传入数值的时候不能用单引号或双引号,否则就是字符串方式进行追加,而不是数值的增加了
ref
在React Native中如何寻找到一个控件呢?在React Native不能使用js的操作(document),我们只能通过ref进行锁定一个控件,以此来操作控件本身的相关属性和状态,但是依据React Native的设计思想并不建议直接操作相关属性,原因很清楚,属性是一个对象的特征,而state是发生变化的条件,我们可以理解成有了某种条件下才能发生属性变化(内部封装性)!外界通过修改相关状态来响应操作。
依照上面state中的例子,我们将定时器去掉,通过一个按钮进行点击,每次点击一下数值增加1
class CountText extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {count: this.props.count};
//每个2秒钟修改一次count
// setInterval(() => {
// this.setState(c => {
// return {count: c.count + 1};
// });
// }, 2000);
}
render() {
return (
<Text>{this.state.count}</Text>
);
}
}
export default class App extends Component<{}> {
pressClick = () => {
this.refs.countText.setState(c => {
return {count: c.count + 1};
});
}
render() {
return (
<View style={styles.container}>
<Button title='点击增加' onPress={this.pressClick}/>
<CountText ref='countText' count={3}/>
</View>
);
}
}
从上面pressClick中看到this.refs,这个可以理解是一个ref集合,然后通过对应的ref定义的值进行操作相关属性即可
运算符
运算符使我们对一些对象进行操作时必要的应用,除了基本通用的运算符之外,这里重点列举一些和Android/java中不一样的地方
==两个等号
在ES6中==会首先转换数据类型,然后进行两者比较,很多时候会得出非常诧异的结果
===三个等号
它不会自动转换数据类型,如果数据类型不一致,返回 false ,如果一致,再比较。
一般情况下我们更多的使用===
FlexBox布局
item属性
- flex
- alignSelf
父容器属性
- flexDiretion
- justifyCotent
- alignItems
- flexWrap
- flexShrink
- flexGrow
在FlexBox中首先需要了解的是布局轴线的概念,在平面坐标系中我们用x,y定义横轴和纵轴。在FlexBox中我们将横轴排版描述成沿z轴排放,当一行排满之后,再沿y轴另取一行继续沿x轴摆放。那么在这个过程中x轴就可以称之为主轴,y轴就可以被称之为副轴。当然如果一开始需要沿着y轴排版,当高度不够时另取一列继续向下摆放,这个时候恰恰和上面相反,主轴就是y轴了,副轴就是x轴。
flex 类似于权重
该属性是一个数值类型,依据数值大小进行父容器空闲区域的划分控件所占区域大小。
可以将其认为是Android中线性布局的一个范例,很容易实现LinearLayout效果。
alignSelf 控件相对于父容器的排列方式
属性值:‘auto’ //默认排版
‘flex-start’ //副轴起始位置
‘flex-end’ //副轴结尾位置
'center' //居中位置
‘stretch’ //拉伸充满
该属性只针对FlexBox中的子元素,优先级改与alignItems。
flexDiretion指定FlexBox主轴
属性值:‘row’ //横轴(x轴)
'column' //纵轴(y轴)
‘row-reverse’ //横轴反方向
'column-reverse' //纵轴反方向
想想在Android中RecyclerView的LinearLayoutManager的reverse参数,就是实例化时最后那个boolean类型的参数。
flexWrap 是否可以换行
属性值:‘wrap’ //换行 自由填充
‘nowrap’ //不换行 **子元素可能会溢出**
这里的换行值得的是默认主轴为横轴(x),当主轴为纵轴时就不是换行了而是列了。
justifyContent 对齐方式
属性值:‘flex-start’ //从开始位置排列摆放,
'flex-end' //从结束位置开始排列摆放
‘center’ //居中
‘space-between’ //在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素与行首对齐,每行最后一个元素与行尾对齐
‘space-around’ //在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素到行首的距离和每行最后一个元素到行尾的距离将会是相邻元素之间距离的一半
类似于Android中gravity(不是layout_gravity),最后两个属性有点例外,关键在于子元素之前相对距离的大小分配
alignItems
属性值:'flex-start'//元素向侧轴起点对齐
'flex-end'//元素向侧轴终点对齐
'center'//元素在侧轴居中。如果元素在侧轴上的高度高于其容器,那么在两个方向上溢出距离相同
'stretch'//弹性元素被在侧轴方向被拉伸到与容器相同的高度或宽度
注意:这个属性和上面属性类似,但是排列方向是以副轴方向
其他布局属性
内边距(padding)和外边距(margin)
在Android中也有padding和margin的概念。padding指的是控件/父容器中内容/子元素距离自己范围边界的距离;margin则是控件/父容器边界与其他组件/父容器边界之间的距离。
定位(position)
这个需要特别强调一下,因为这个决定了位置摆放的计算规则
- absolute 生成绝对定位的元素,元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定 (Android中的FrameLayout)
- relative 生成相对定位的元素,相对于其正常位置进行定位。因此,"left:20" 会向元素的 LEFT 位置添加 20 像素
单位
在React Native中尺寸是没有单位,在style中定义的padding、margin、size等都不携带dp、px、pt等长度单位。当React Native运行环境是Android时,React Native会将单位解析成dp、sp