返回 导航

React / React Native

hangge.com

React Native - flexbox布局介绍、及应用的组件化构建(附样例)

作者:hangge | 2017-01-19 08:10
React Native Web 中的 flexbox 布局引入进来使用,使得视图局部变得更加简单。关于 Web 里的 flexbox,以及相关属性介绍,及样例图片可以参考我之前些的这几篇文章。
CSS3 - 弹性盒子模型(flexbox)详解1(基本概念介绍、浏览器支持情况)
CSS3 - 弹性盒子模型(flexbox)详解2(伸缩容器的属性介绍、及样例)
CSS3 - 弹性盒子模型(flexbox)详解3(伸缩项目的属性介绍、及样例)
HTML5 - flexbox布局样例(实现一个盒子模型的效果展示)

一、flexbox的属性介绍

React Native 目前主要支持 flexbox 的属性有:
alignItemsalignSelfflexflexDirectionflexWrapjustifyContent

1,alignItems

该属性用来定义伸缩项目在伸缩容器的交叉轴上的对齐方式,可选值有:flex-startflex-endcenterstretch

2,alignSelf

该属性用来设置单独的伸缩项目在交叉轴上的对齐方式,会覆盖默认的对齐方式。可选值有:autoflex-startflex-endcenterstretch

3,flex

该属性定义伸缩项目的放大比例,默认值是 0,即表示如果存在剩余空间,也不放大。
如果将所有的伸缩项目的 flex 设置为 1,那么每个伸缩项目将设置为一个大小相等的剩余空间。
如果又将其中一个伸缩项目的 flex 设置为 2,那么这个伸缩项目所占的剩余空间是其他伸缩项目所占的剩余空间的两倍。

4,flexDirection

改属性可以指定主轴的方向。可选值有:rowcolumn。注意和 Web 不同,React Native 默认的是 column


5,flexWrap

该属性主要用来指定伸缩容器的主轴线方向空间不足的情况下,是否换行以及如何换行。可选值有:nowrapwrap

6,justifyContent

该属性用来定义伸缩项目沿主轴线的对齐方式,可选值有:flex-startflex-endcenterspace-betweenspace-around

二 、flexbox使用样例

下面我们使用 flexbox 布局来实现一个盒子模型展示页面。

1,效果图


2,样例代码

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
} from 'react-native';

export default class HelloWorld extends Component {
  render() {
    return (
      <View style={[BoxStyles.margginBox]}  ref="lab1">
        <View style={[BoxStyles.box,BoxStyles.height400,BoxStyles.width400]}>
          <View style={[BoxStyles.top,BoxStyles.height50,BoxStyles.bgorange]}>
            <Text style={BoxStyles.black}>top</Text></View>
          <View style={[BoxStyles.borderBox]}>
            <View style={[BoxStyles.left,BoxStyles.bgorange]} >
              <Text style={BoxStyles.black}>left</Text></View>
            <View style={[BoxStyles.box,BoxStyles.height300]}>
              <View style={[BoxStyles.top,BoxStyles.height50,BoxStyles.bgyellow]}>
                <Text style={BoxStyles.black}>top</Text></View>
              <View style={[BoxStyles.paddingBox]}>
                <View style={[BoxStyles.left,BoxStyles.bgyellow]} >
                  <Text style={BoxStyles.black}>left</Text></View>
                <View style={[BoxStyles.box,BoxStyles.height200]}>
                  <View style={[BoxStyles.top,BoxStyles.height50,BoxStyles.bggreen]}>
                    <Text style={BoxStyles.black}>top</Text></View>
                  <View style={[BoxStyles.elementBox]}>
                    <View style={[BoxStyles.left,BoxStyles.bggreen]} >
                      <Text style={BoxStyles.black}>left</Text></View>
                    <View style={[BoxStyles.box,BoxStyles.height100,BoxStyles.bgblue]}>
                      <View  style={[BoxStyles.label]}>
                        <Text style={BoxStyles.white}>element</Text></View>
                      <View style={[BoxStyles.widthdashed]} ></View>
                      <View style={[BoxStyles.heightdashed]} ></View>
                      <View style={[BoxStyles.measureBox]} >
                        <View style={[BoxStyles.right]}>
                          <Text style={[BoxStyles.black]}>height</Text></View>
                      </View>
                      <View style={[BoxStyles.bottom,BoxStyles.height50]}>
                        <Text style={BoxStyles.black}>width</Text></View>
                    </View>
                    <View style={[BoxStyles.right,BoxStyles.bggreen]}>
                      <Text style={BoxStyles.black}>right</Text>
                    </View>
                  </View>
                  <View style={[BoxStyles.bottom,BoxStyles.height50,BoxStyles.bggreen]}>
                    <Text style={BoxStyles.black}>bottom</Text></View>
                  <View style={[BoxStyles.label]}>
                    <Text style={BoxStyles.white}>padding</Text></View>
                </View>
                <View style={[BoxStyles.right,BoxStyles.bgyellow]}>
                  <Text style={BoxStyles.black}>right</Text>
                </View>
              </View>
              <View style={[BoxStyles.bottom,BoxStyles.height50,BoxStyles.bgyellow]}>
                <Text style={BoxStyles.black}>bottom</Text></View>
              <View style={[BoxStyles.label]}><Text style={BoxStyles.white}>border</Text></View>
            </View>
            <View style={[BoxStyles.right,BoxStyles.bgorange]}>
              <Text style={BoxStyles.black}>right</Text></View>
          </View>
          <View style={[BoxStyles.bottom,BoxStyles.height50,BoxStyles.bgorange]}>
            <Text style={BoxStyles.black}>bottom</Text></View>
          <View style={[BoxStyles.label]} ><Text style={BoxStyles.white}>margin</Text></View>
        </View>
      </View>
    );
  }
}

const BoxStyles = StyleSheet.create({
  "height50": {
    height: 50,
  },
  "height400": {
    height: 400,
  },
  "height300": {
    height: 300,
  },
  "height200": {
    height: 200,
  },
  "height100": {
    height: 100,
  },
  "width400": {
    width: 400,
  },
  "width300": {
    width: 300,
  },
  "width200": {
    width: 200,
  },
  "width100": {
    width: 100,
  },
  "bgorange": {
    backgroundColor: "#F9CC9D",
  },
  "bgyellow": {
    backgroundColor: "#FDDD9B",
  },
  "bggreen": {
    backgroundColor: "#C2CF8A",
  },
  "bgblue": {
    backgroundColor: "#8BB5C0",
  },
  "margginBox":{
    "position": "absolute",
    "top": 50,
    "paddingLeft":7,
    "paddingRight":7,
  },
  "box": {
    flexDirection: "column",
    flex: 1,
    position: "relative",
  },
  "label": {
    top: 0,
    left: 0,
    paddingTop: 0,
    paddingRight: 3,
    paddingBottom: 3,
    paddingLeft: 0,
    position: "absolute",
    backgroundColor: "#000000",
  },
  "top": {
    justifyContent: "center",
    alignItems: "center",
  },
  "bottom": {
    justifyContent: "center",
    alignItems: "center",
  },
  "left": {
    width: 50,
    justifyContent: "space-around",
    alignItems: "center",
  },
  "right": {
    width: 50,
    justifyContent: "space-around",
    alignItems: "center",
  },
  "heightdashed": {
    bottom: 0,
    top: 0,
    right: 20,
    borderLeftWidth: 1,
    position: "absolute",
    borderLeftColor: "#000000"
  },
  "widthdashed": {
    bottom: 25,
    left: 0,
    right: 0,
    borderTopWidth: 1,
    position: "absolute",
    borderTopColor: "#000000"
  },
  "black": {
    color: "#000000",
    fontWeight:"900",
  },
  "white": {
    color: "white",
    fontWeight:"900",
  },
  "borderBox":{
    flex: 1,
    justifyContent: "space-between",
    flexDirection: "row",
  },
  "paddingBox":{
    flex: 1,
    justifyContent: "space-between",
    flexDirection: "row",
  },
  "elementBox":{
    flex: 1,
    justifyContent: "space-between",
    flexDirection: "row",
  },
  "measureBox":{
    flex: 1,
    flexDirection: "row",
    justifyContent: "flex-end",
    alignItems:"flex-end"
  }
});

AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

三、通过组件化来构建应用

Reac 最大的特点就是功能组件化。上面代码中我们只创建一个组件,用来来从头到位实现整个功能。代码看起来比较繁杂。
我们大可将其拆分成多个组件,把公共部分提取出来。这样既提高代码可读性,也使得代码更加简练。
(1)比如我们还是实现和上面一样的功能,但这次我们分成 6 个组件来共同实现。具体功能介绍如下:
  • 对于不同的显示层级,我们分别定义了 MargginBoxBorderBoxPaddingBox ElementBox 4个组件。
  • 同时定义一个最外层的容器组件 BoxContainer,将上面4个子组件嵌套包含进来,并最终渲染到页面上。
  • 由于 MargginBoxBorderBoxPaddingBox 3个组件的显示效果相近,所以我们将公共的部分提取出来成为一个新组件(Box)供它们调用。
  • 这里注意一下 {this.props.children},它会将当前组件内部的子组件全部渲染出来。 
(2)下面是完整的代码:
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
} from 'react-native';

class BoxContainer extends Component {
  render() {
    return (
      <MargginBox>
        <BorderBox>
          <PaddingBox>
            <ElementBox>
            </ElementBox>
          </PaddingBox>
        </BorderBox>
      </MargginBox>
    )
  }
}

class MargginBox extends Component {
  render() {
    return (
      <View style={[BoxStyles.margginBox]}>
        <Box childName="borderBox"  height="height400" width="width400" boxName="margin"
         classBg="bgorange">{this.props.children}</Box>
      </View>
    );
  }
}

class BorderBox extends Component {
  render() {
    return (
      <Box childName="paddingBox"  height="height300" width="width300" boxName="border"
      classBg="bggreen" >{this.props.children}</Box>
    );
  }
}

class PaddingBox extends Component {
  render() {
    return (
      <Box childName="elementBox"  height="height200" width="width200" boxName="padding"
       classBg="bgyellow" >{this.props.children}</Box>
    )
  }
}

class ElementBox extends Component {
  render() {
    return (
      <View style={[BoxStyles.box,BoxStyles.height100,BoxStyles.bgblue]}>
        <View style={[BoxStyles.measureBox]}>
          <View style={[BoxStyles.right]}><Text>height</Text></View>
        </View>
        <View style={[BoxStyles.bottom,BoxStyles.height50]} ><Text>width</Text></View>
        <View style={[BoxStyles.label]}><Text style={[BoxStyles.white]}>element</Text></View>
        <View style={[BoxStyles.widthdashed]}></View>
        <View style={[BoxStyles.heightdashed]}></View>
      </View>
    )
  }
}

class Box extends Component {
  render() {
    return (
      <View style={[BoxStyles.box,BoxStyles[this.props.width],BoxStyles[this.props.height]]}>
        <View style={[BoxStyles.top,BoxStyles.height50,BoxStyles[this.props.classBg]]}>
          <Text>top</Text>
        </View>
        <View style={[BoxStyles[this.props.childName]]}>
          <View style={[BoxStyles.left,BoxStyles[this.props.classBg]]}>
            <Text>left</Text>
          </View>
            {this.props.children}
          <View style={[BoxStyles.right,BoxStyles[this.props.classBg]]}>
            <Text>right</Text>
          </View>
        </View>
        <View style={[BoxStyles.bottom,BoxStyles.height50,BoxStyles[this.props.classBg]]}>
          <Text>bottom</Text>
        </View>
        <View style={[BoxStyles.label]}>
          <Text style={[BoxStyles.white]}>{this.props.boxName}</Text>
        </View>
      </View>
    );
  }
}

const BoxStyles = StyleSheet.create({
  "height50": {
    height: 50,
  },
  "height400": {
    height: 400,
  },
  "height300": {
    height: 300,
  },
  "height200": {
    height: 200,
  },
  "height100": {
    height: 100,
  },
  "width400": {
    width: 400,
  },
  "width300": {
    width: 300,
  },
  "width200": {
    width: 200,
  },
  "width100": {
    width: 100,
  },
  "bgorange": {
    backgroundColor: "#F9CC9D",
  },
  "bgyellow": {
    backgroundColor: "#FDDD9B",
  },
  "bggreen": {
    backgroundColor: "#C2CF8A",
  },
  "bgblue": {
    backgroundColor: "#8BB5C0",
  },
  "margginBox":{
    "position": "absolute",
    "top": 50,
    "paddingLeft":7,
    "paddingRight":7,
  },
  "box": {
    flexDirection: "column",
    flex: 1,
    position: "relative",
  },
  "label": {
    top: 0,
    left: 0,
    paddingTop: 0,
    paddingRight: 3,
    paddingBottom: 3,
    paddingLeft: 0,
    position: "absolute",
    backgroundColor: "#000000",
  },
  "top": {
    justifyContent: "center",
    alignItems: "center",
  },
  "bottom": {
    justifyContent: "center",
    alignItems: "center",
  },
  "left": {
    width: 50,
    justifyContent: "space-around",
    alignItems: "center",
  },
  "right": {
    width: 50,
    justifyContent: "space-around",
    alignItems: "center",
  },
  "heightdashed": {
    bottom: 0,
    top: 0,
    right: 20,
    borderLeftWidth: 1,
    position: "absolute",
    borderLeftColor: "#000000"
  },
  "widthdashed": {
    bottom: 25,
    left: 0,
    right: 0,
    borderTopWidth: 1,
    position: "absolute",
    borderTopColor: "#000000"
  },
  "black": {
    color: "#000000",
    fontWeight:"900",
  },
  "white": {
    color: "white",
    fontWeight:"900",
  },
  "borderBox":{
    flex: 1,
    justifyContent: "space-between",
    flexDirection: "row",
  },
  "paddingBox":{
    flex: 1,
    justifyContent: "space-between",
    flexDirection: "row",
  },
  "elementBox":{
    flex: 1,
    justifyContent: "space-between",
    flexDirection: "row",
  },
  "measureBox":{
    flex: 1,
    flexDirection: "row",
    justifyContent: "flex-end",
    alignItems:"flex-end"
  }
});

AppRegistry.registerComponent('HelloWorld', () => BoxContainer);
评论

全部评论(0)

回到顶部