React Native

    React-native之Flexbox

    发布时间
    April 21, 2023
    阅读时间
    4 min read
    作者
    Felix
    访问
    公开阅读

    1、关于Flexbox

    在将flexbox引入css前,构建布局的各种css属性都比较粗糙,而且很容易出错。而flexbox通过抽象了很多属性来解决问题。字如其名flexbox的意思就是一个具有弹性的盒子模型。我们画个图:假设你有一个容器和它的子元素,它看起来可以是这样的。

    image.png

    Flexbox容器有二个轴,即(向上/向下)或(左/右)。

    2、实操

    我们直接上代码吧,这是一个js模块,而不是css模块。如果我们要声明rn的样式,我们需要去定义一个对象然后调用StyleSheet.create()最后抛出它在你的模块中。但是我们需要注意的是rn只支持驼峰命名

    import { Platform, StyleSheet, StatusBar } from 'react-native'
    export default StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'ghostwhite',
        ...Platform.select({
          ios: { paddingTop: 20 },
          android: { paddingTop: StatusBar.currentHeight },
        }),
      },
      box: {
        width: 100,
        height: 100,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'lightgray',
      },
      boxText: {
        color: 'darkslategray',
        fontWeight: 'bold',
      },
    })
    
    
    ```
    
    然后我们看到刚才我写了这样一段代码,这里其实就是根据你的移动端去选择样式。
    
    ```js
    ...Platform.select({
      ios: { paddingTop: 20 },
      android: { paddingTop: StatusBar.currentHeight },
    }),
    
    ```
    
    ok,我们看一下在`rn`组件中如何使用
    
    ```javascript
    import { Text, View } from 'react-native'
    import styles from './styles'
    export default function App() {
      return (
        <View style={styles.container}>
          <View style={styles.box}>
            <Text style={styles.boxText}>I'm in a box</Text>
          </View>
        </View>
      )
    }
    
    
    ```
    
    这些样式将通过样式属性分配给每个组件。我们来看看它的表现。
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/React%20Native%20Flexbox%20(1).webp?updatedAt=1739875781432)
    
    # 3、Styled-components样式组件库使用
    
    `Styled-components`是一个`css-in-js`的库为我们的组件去提供样式,如我们去直接看看怎么使用吧。当然只是介绍一下,我们还是使用`styleSheet`。
    
    首先下载依赖
    
    ```sh
    yarn add styled-components
    
    ```
    
    然后我们写点代码
    
    ```js
    import styled from "styled-components/native";
    const Box = styled.View'
        width: 100px;
        height: 100px;
        justify-content: center;
        align-items: center;
        background-color: lightgray;
    ';
    const BoxText = styled.Text'
        color: darkslategray;
        font-weight: bold;
    ';
    
    ```
    
    使用
    
    ```javascript
    const App = () => {
    return (
        <Box>
            <BoxText>I'm in a box</BoxText>
        </Box>
    );
    
    };
    
    ```
    
    # 4、基础Flexbox
    
    接下来主要讲一下`rn`中的几种常见布局和`flexbox`的实战
    
    ## 4.1、三栏布局
    
    普通的从上到下的三栏布局。
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/React%20Native%20Flexbox%20(3).webp?updatedAt=1739875781734)
    
    ‘
    
    你可以把`view`理解成`div`,`text`理解成`p`。
    
    ```js
    import { Text, View } from 'react-native'
    import styles from './styles'
    export default function App() {
      return (
        <View style={styles.container}>
          <View style={styles.box}>
            <Text style={styles.boxText}>#1</Text>
          </View>
          <View style={styles.box}>
            <Text style={styles.boxText}>#2</Text>
          </View>
          <View style={styles.box}>
            <Text style={styles.boxText}>#3</Text>
          </View>
        </View>
      )
    }
    
    ```
    
    `flexDirection`属性是决定了主轴的方向,上到下或者左到右,而`alignItem`和`justifyContent`属性决定了元素的排列和间隔。
    
    ```php
    import { Platform, StyleSheet, StatusBar } from 'react-native'
    export default StyleSheet.create({
      container: {
        flex: 1,
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-around',
        backgroundColor: 'ghostwhite',
        ...Platform.select({
          ios: { paddingTop: 20 },
          android: { paddingTop: StatusBar.currentHeight },
        }),
      },
      box: {
        width: 300,
        height: 100,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'lightgray',
        borderWidth: 1,
        borderStyle: 'dashed',
        borderColor: 'darkslategray',
      },
      boxText: {
        color: 'darkslategray',
        fontWeight: 'bold',
      },
    })
    
    
    ```
    
    而如果我们想让它左右两边填满那?就像这样
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/React%20Native%20Flexbox%20(3).webp?updatedAt=1739875781734)
    
    我们可以加入`alignSelf`这个属性,这个属性的意思是根据主轴`flexDirection`的方向,改变宽度或者高度(column改变的就是宽度,row改变的就是高度)去填充空白,动态计算高度或宽度。像这样就是会填满你屏幕的宽度。
    
    ```js
      box: {
        height: 100,
        justifyContent: 'center',
        // 
        alignSelf: 'stretch',
        alignItems: 'center',
        backgroundColor: 'lightgray',
        borderWidth: 1,
        borderStyle: 'dashed',
        borderColor: 'darkslategray',
      },
    
    ```
    
    当我们把手机横过去
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/React%20Native%20Flexbox%20(4).webp?updatedAt=1739875781712)
    
    我们稍微优化一下,正好也写一下横向的布局,上面的样式太`抽象`了写得。
    
    ```js
    import { Text, View, StatusBar } from 'react-native'
    import styles from './styles'
    import Box from './Box'
    export default function App() {
     return (
       <View style={styles.container}>
         <Box>#1</Box>
         <Box>#2</Box>
       </View>
     )
    }
    
    
    ```
    
    ```js
    import { PropTypes } from 'prop-types'
    import { View, Text } from 'react-native'
    import styles from './styles'
    export default function Box({ children }) {
     return (
       <View style={styles.box}>
         <Text style={styles.boxText}>{children}</Text>
       </View>
     )
    }
    Box.propTypes = {
     children: PropTypes.node.isRequired,
    }
    
    ```
    
    这个就是会拉伸至整个屏幕高度的横向布局
    
    ```php
    import { Platform, StyleSheet, StatusBar } from 'react-native'
    export default StyleSheet.create({
      container: {
        flex: 1,
        flexDirection: 'row',
        backgroundColor: 'ghostwhite',
        alignItems: 'center',
        justifyContent: 'space-around',
        ...Platform.select({
          ios: { paddingTop: 20 },
          android: { paddingTop: StatusBar.currentHeight },
        }),
      },
      box: {
        width: 100,
        justifyContent: 'center',
        alignSelf: 'stretch',
        alignItems: 'center',
        backgroundColor: 'lightgray',
        borderWidth: 1,
        borderStyle: 'dashed',
        borderColor: 'darkslategray',
      },
      boxText: {
        color: 'darkslategray',
        fontWeight: 'bold',
      },
    })
    
    
    ```
    
    我们来看看它的表现
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/1b7f4a002d1045a882faf4b2a2ea521a~tplv-k3u1fbpfcp-zoom-in-crop-mark_1512_0_0_0.webp?updatedAt=1739875782894)
    
    当我们把手机横过去
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/4bf95f1a6db64d708edd014bbab07159~tplv-k3u1fbpfcp-zoom-in-crop-mark_1512_0_0_0.webp?updatedAt=1739875782855)
    
    # 5、稍微复杂一点的flexBox
    
    假设我们要实现这样一个效果,我们该如何实现?
    
    ![image.png](https://ik.imagekit.io/leiakito/react%20Core%20scheduling%20principles/react-native-flexbox/4da8595a2c834d6ba5bdabc8e1dd8882~tplv-k3u1fbpfcp-zoom-in-crop-mark_1512_0_0_0.webp?updatedAt=1739875781677)
    
    在我们的意识中,整个布局有``、``。那我们同样也可以抽象出`col`、`row`组件分别代表行列。我们直接上代码吧。
    
    可以看到我们分别确定了`col`、`row`的方向和排列。
    
    ```js
    import { Platform, StyleSheet, StatusBar } from 'react-native'
    
    export default StyleSheet.create({
      container: {
        flex: 1,
        flexDirection: 'column',
        backgroundColor: 'ghostwhite',
        alignItems: 'center',
        justifyContent: 'space-around',
        ...Platform.select({
          ios: { paddingTop: 40 },
          android: { paddingTop: StatusBar.currentHeight },
        }),
      },
    
      box: {
        height: 100,
        width: 100,
        justifyContent: 'center',
        alignItems: 'center',
        borderWidth: 1,
        borderStyle: 'dashed',
        borderColor: 'darkslategray',
        backgroundColor: 'lightgray',
      },
    
      boxText: {
        color: 'darkslategray',
        fontWeight: 'bold',
      },
    
      row: {
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'space-around',
        alignSelf: 'stretch',
      },
    
      column: {
        flex: 1,
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-around',
        alignSelf: 'stretch',
      },
    })
    
    ```
    
    **组件部分**
    
    `app`
    
    ```js
    import { View, StatusBar } from 'react-native'
    import styles from './styles'
    import Row from './Row'
    import Col from './Col'
    import Box from './Box'
    
    export default function App() {
      return (
        <View style={styles.container}>
          <StatusBar hidden={false} />
          <Row>
            <Col>
              <Box>#1</Box>
              <Box>#2</Box>
            </Col>
            <Col>
              <Box>#3</Box>
              <Box>#4</Box>
            </Col>
          </Row>
          <Row>
            <Col>
              <Box>#5</Box>
              <Box>#6</Box>
            </Col>
            <Col>
              <Box>#7</Box>
              <Box>#8</Box>
            </Col>
          </Row>
          <Row>
            <Col>
              <Box>#9</Box>
              <Box>#10</Box>
            </Col>
            <Col>
              <Box>#11</Box>
              <Box>#12</Box>
            </Col>
          </Row>
        </View>
      )
    }
    
    
    ```
    
    `col`
    
    ```javascript
    import PropTypes from 'prop-types'
    import { View } from 'react-native'
    import styles from './styles'
    
    export default function Column({ children }) {
      return <View style={styles.column}>{children}</View>
    }
    
    Column.propTypes = {
      children: PropTypes.node.isRequired,
    }
    
    
    ```
    
    `row`
    
    ```javascript
    import PropTypes from 'prop-types'
    import { View } from 'react-native'
    import styles from './styles'
    
    export default function Row({ children }) {
      return <View style={styles.row}>{children}</View>
    }
    
    Row.propTypes = {
      children: PropTypes.node.isRequired,
    }
    
    
    ```
    
    `box`
    
    ```javascript
    import React from 'react'
    import PropTypes from 'prop-types'
    import { View, Text } from 'react-native'
    import styles from './styles'
    
    export default function Box({ children }) {
      return (
        <View style={styles.box}>
          <Text style={styles.boxText}>{children}</Text>
        </View>
      )
    }
    
    Box.propTypes = {
      children: PropTypes.node.isRequired,
    }
    
    ```
    
    # 6、总结
    
    我们在这节里知道了`rn`中最常见的布局方式,需要同学们自己下去多练一下,还是比较简单的,有问题可以问我。加学习群看[沸点](https://juejin.cn/user/400646714977431/pins).
    

    评论

    加入讨论

    0 条评论
    登录后评论

    还没有评论,来占个沙发吧。

    React-native之Flexbox | 鱼的博客 | 鱼的博客