在浏览器中,我们用div作为基本容器,在RN中,我们使用View作为基本容器,它们的功能几乎是一样的,主要不同的是容器的定位(position)和布局(display)规则不一样。本篇博客主要就是分析一下它们之间的差异,以及在RN开发中如何使用定位和布局。
容器定位
定位,用position属性表示,其可准确地定义元素出现的位置的规则。
在浏览器中(即PC端),position属性主要包含有4个属性值,分别为static、relative、absolute、fixed。
属性值 | 描述 | 所属类别 |
---|---|---|
static | 默认值,元素遵循默认的文档流。 | 默认 |
relative | 元素遵循默认的文档流。 相对于其父级元素的原位置进行定位,周围元素忽略该元素的移动。 需要设置top、bottom、left、right值进行定位。 | 相对定位 |
absolute | 元素脱离正常文档流。 相对于包含该元素的最近一级的非静态定位(即非static)的元素进行定位,若不满足条件,则会根据最外层的window进行定位。 需要设置top、bottom、left、right值进行定位。 | 绝对定位 |
fixed | 元素脱离正常文档流。 相对于最外层的window进行定位,固定在屏幕上的某个位置,不因屏幕滚动而消失。 需要设置top、bottom、left、right值进行定位。 | 绝对定位 |
在RN中,position属性只有relative(默认值)和absolute。记住这一点很重要。因为在RN开发中,意味着View容器在不设置position(默认)的情况下,通过top、bottom、left、right值进行定位时,是不会影响周围的元素的。我们用代码证明一下:
import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';
class MainView extends Component {
render(){
return (
<View>
<View style={styles.redViewStyle} />
<View style={styles.greenViewStyle} />
</View>
);
}
}
const styles = StyleSheet.create({
redViewStyle: {
height: 50,
backgroundColor: 'red',
top: 10
},
greenViewStyle: {
height: 50,
backgroundColor: 'green'
}
});
export default MainView;
代码中定义了一个组件MainView,组件中有两个分别为红色和绿色背景色的View容器,并且红色容器距离顶部10dp(设备独立像素),关于单位的理解,在移动设备中用的尺寸单位并不是浏览器中常用的物理像素,后面会写一篇博客再详细介绍。最终显示效果如下:
事实证明,我们对RN的默认定位理解是正确的。当然,如果要测试绝对定位(absolute)也是没问题的,只需要把背景色为green绿色的容器设置定位为position: absolute,并给该容器添加一个100%的宽度,最终呈现的效果是:绿色容器和红色容器重叠在一起且遮住了红色容器,这个大家可以手动修改上面这段代码试一下。
这点知识在RN开发中是必须要懂的,即定位默认值的差异,初学者在这一点上会很容易混淆从而造成不必要的麻烦。
布局规则
布局规则要比定位更加重要。
布局,在样式表中用display表示,用于定义建立布局时容器的显示类型。在浏览器中,常用的几种布局类型有:
属性 | 描述 |
---|---|
block | 默认值,表示元素的宽度占满了整个浏览器的宽度,且每一行只允许容纳一个block类型元素 |
inline | 表示元素的宽度只等于内容所在的宽度,设置width无效 |
inline-block | 当没设置宽度时与inline效果相同,但设置width后,以width为准,与vertical-align:middle配合使用可实现内容垂直居中 |
inherit | 规定应该从父元素继承 display 属性的值 |
flex | 该元素按比例自动扩展宽度或高度,扩展的宽高取决于flexDirection设置的主从轴方向 |
none | 元素将不会被显示 |
在RN中,display属性只有flex和none,默认值为flex,我们称之为弹性布局。这里要注意一点,在RN中的弹性布局主轴方向(属性flexDirection)默认值是column,而在浏览器中则相反,其主轴方向默认值为row。那么怎么理解这个主、从轴方向呢?以RN为例,我们看下面这个图:
alignItems属性是指父组件设置其在从轴方向的元素的位置,这里可先不管。以左图为例,其定义了一个父组件parent,根据RN对默认布局的定义可知,容器的布局均为flex弹性布局,并且默认主轴方向为flexDirection:column,换算成坐标系来说主轴就是纵向的Y轴,那么从轴就是X轴。按照弹性布局规则:弹性布局中子组件将在从轴方向自动拉伸,这意味着如果子组件Button在不设置固定宽度width值时,其宽度将自动延伸为100%,但要正确显示出来还需为其设置一个高度值height。反之,如右图,flexDirection:row,则主轴方向为横向的X轴,其高度会延伸为100%,要正确显示同样需为其设置一个宽度值width。
根据上面的图例,可能有朋友会说,既然子组件会在从轴方向自动延伸为100%,那么我想要主轴方向也为100%怎么办,那么这时只需要设置flex:1即可实现,它表示让子组件的尺寸size沿着其父组件设置的主轴方向拉伸,直到在主轴方向上填满父组件。效果如下图:
如果两个同层级的子组件都把flex:1会怎么样?大家可以试一下噢!你会发现两个子组件将会平分父组件的主轴方向的剩余空间。另外在RN使用弹性布局中,我们经常会用到两个属性来管理其子组件的对齐方式,这两个属性为:justifyContent和alignItems,前者表示对其子组件在主轴方向上的位置管理,后者表示对其子组件在从轴方向上的位置管理。我们举个例子,假设以默认布局方向flexDirection:column为例,这时主轴为Y轴,从轴为X轴。
justifyContent管理主轴的对齐方式:
属性 | 描述 |
---|---|
flex-start | 从最顶部开始布局所有子元素 |
flex-end | 从最底部开始布局所有子元素 |
center | 居中布局所有子元素 |
space-between | 将第一个元素布局在最顶部,最后一个子元素布置在最底部,将空白部分平均分配在所有子元素之间。 |
space-around | 将空白部分平均分配到所有子元素之间,包括上下边界也分配空白。 |
alignItems管理从轴的对齐方式:
属性 | 描述 |
---|---|
flex-start | 从最左边开始布局所有子元素 |
flex-end | 从最右边开始布局所有子元素 |
center | 居中布局所有子元素 |
我们用代码证明一下:
import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';
class MainView extends Component {
render(){
return (
<View style={styles.containerStyle}>
<View style={styles.redViewStyle} />
<View style={styles.greenViewStyle} />
</View>
);
}
}
const styles = StyleSheet.create({
containerStyle: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center'
},
redViewStyle: {
backgroundColor: 'red',
width: 50,
height: 50
},
greenViewStyle: {
backgroundColor: 'green',
width: 100,
height: 100
}
});
export default MainView;
最终显示效果如下:
主轴方向对齐方式为flex-end,表示在最底部;从轴方向对齐方式为center,表示水平居中,证明我们的理解是正确的。
以上就是RN入门必须懂的容器定义与布局规则的全部内容,这点在RN开发中很重要,因为这些很细节的知识会贯穿整个RN的开发过程,最好都能牢记。