Ant Design for React Native精简笔记

背景

Ant Design是一套不错的UI组件库,功能强大。但是依赖了很多其他的组件,在RN6.3以后要自己安装以下组件才能正常使用。

yarn add @react-native-community/cameraroll @react-native-community/picker @react-native-community/segmented-control @react-native-community/slider @react-native-community/viewpager @react-native-community/async-storage

随着RN版本的不断更新,这里有一些组件渐渐已经过时。或者有更好的替代了。

我以前也写过相关的文章:

虽然Ant Design非常火,但是不得不承认Ant Design for RN在RN开发者中并不火。而且更新的频率不太高。因为有很多更好的选择。在我看来Ant Design for RN还是有些臃肿了,依赖太多会导致APP体积增加。对于极简主义的我还是不能接受的。

随着编码能力的提升,有很多组件可以自己设计出来了。Ant Design for RN在我的项目中渐渐的可有可无,但是为了照顾以前开发的老组件,我就萌生了自己实现一些我们项目中常用的Ant 组件的想法。

grid组件

这个是我用的最多的组件,没有之一。用起来比较方便。如果不用Ant Design for RN怎么来自己实现呢?我自己在实现的过程中,发现Ant Design for RN本身就是开源的。所以就直接把源码拿过来简单修改就可以使用了。
源码地址:
https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/grid/index.tsx

主要代码如下,其他的依赖的内容可以原封不动从Ant Design for RN源码中复制,这里我就不浪费版面了。

import React from 'react';
import {
    
    
  Dimensions,
  Image,
  StyleProp,
  StyleSheet,
  Text,
  ViewStyle,
} from 'react-native';
import Flex from '../flex/index';
import {
    
    DataItem, GridPropsType} from './PropsType';
//import GridStyles from './style/index';

//定义接口
export interface GridProps extends GridPropsType {
    
    
  itemStyle?: StyleProp<ViewStyle>;
}

//定义Grid的属性
export default class Grid extends React.Component<GridProps, any> {
    
    
  static defaultProps: GridProps = {
    
    
    data: [],
    hasLine: true,
    isCarousel: false,
    columnNum: 4,
    carouselMaxRow: 2,
    itemStyle: {
    
    },
  };

  //获取每个表格的样式,高度根据屏幕宽度计算得出
  getFlexItemStyle(columnNum: number) {
    
    
    return {
    
    
      height: Dimensions.get('window').width / columnNum,
      borderRightWidth: this.props.hasLine ? StyleSheet.hairlineWidth : 0,
    };
  }

  render() {
    
    
    //获取相关属性参数
    const {
    
    data, hasLine, onPress = () => {
    
    }} = this.props;
    //获取列数
    const columnNum = this.props.columnNum;
    //获取用户自定义的样式
    const customItemStyle = this.props.itemStyle;
    //设置最大的行数
    //获取数据的长度
    const dataLength = (data && data.length) || 0;
    //计算行数
    const rowCount = Math.ceil(dataLength / columnNum);
    //如果用户传递属性了,则使用用户传递的方法,否则使用默认的方法
    const renderItem =
      this.props.renderItem ||
      ((dataItem: DataItem, index: number) => (
        <Flex
          direction="column"
          justify="center"
          style={
    
    {
    
    flex: 1}}
          onPress={
    
    () => onPress(dataItem, index)}>
          {
    
    React.isValidElement(dataItem.icon) ? (
            dataItem.icon
          ) : (
            // 如果不是react组件,则显示图片
            <Image source={
    
    {
    
    uri: dataItem.icon}} style={
    
    styles.icon} />
          )}
          <Text style={
    
    styles.text}>{
    
    dataItem.text}</Text>
        </Flex>
      ));

    //获取每一个item的样式
    const flexItemStyle = this.getFlexItemStyle(columnNum);
    const rowsArr: any[] = []; //用于存储所有的item

    //处理每一行的数据
    for (let i = 0; i < rowCount; i++) {
    
    
      //存储单行的内容
      const rowArr: any[] = [];
      //处理一行中,第一列的数据
      for (let j = 0; j < columnNum; j++) {
    
    
        //计算总index的值
        const dataIndex = i * columnNum + j;
        if (dataIndex < dataLength) {
    
    
          //如果数据存在,则取出来待用
          const el = data && data[dataIndex];
          //把这一行的内容push进来
          rowArr.push(
            <Flex.Item
              key={
    
    j}
              style={
    
    [
                styles.grayBorderBox,
                flexItemStyle,
                {
    
    
                  borderLeftWidth:
                    hasLine && j === 0 ? StyleSheet.hairlineWidth : 0,
                },
                customItemStyle,
              ]}
              onPress={
    
    () => onPress(el, dataIndex)}>
              {
    
    el && renderItem(el, dataIndex)}
            </Flex.Item>,
          );
        } else {
    
    
          //如果数据为空,则渲染一个空的格子
          rowArr.push(
            <Flex.Item
              key={
    
    j}
              style={
    
    [styles.grayBorderBox, flexItemStyle, customItemStyle]}
            />,
          );
        }
      }
      //盒子的边框样式
      const boxBorderStyle = {
    
    
        borderTopWidth: hasLine && i === 0 ? StyleSheet.hairlineWidth : 0,
        borderBottomWidth: hasLine ? StyleSheet.hairlineWidth : 0,
      };
      //把每一行的item塞进来
      rowsArr.push(
        <Flex key={
    
    i} style={
    
    [styles.grayBorderBox, boxBorderStyle]}>
          {
    
    rowArr}
        </Flex>,
      );
    }

    //根据不同的情况,输入不同的内容
    return <Flex direction="column">{
    
    rowsArr}</Flex>;
  }
}

const styles = StyleSheet.create({
    
    
  container: {
    
    
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  grayBorderBox: {
    
    
    borderColor: '#dddddd',
  },
  icon: {
    
    
    width: 22,
    height: 22,
  },
  text: {
    
    
    fontSize: 12,
    color: '#000000',
    marginTop: 8,
  },
});

icon组件

这个组件是我使用第2多的组件。移植起来相对上面的容易一些,因为依赖没有上面的多。
详细使用方法见:
https://github.com/ant-design/ant-design-icons/tree/master/packages/icons-react-native

简单介绍:

yarn add @ant-design/icons-react-native

然后把字体文件手动复制到项目中。实现方法不是本文重点,请参考:
《2020年React Native使用Ant Design Mobile RN组件》
https://blog.csdn.net/lxyoucan/article/details/108334465
安卓为例:
项目目录中复制以下字体(node_modules/@ant-design/icons-react-native/fonts),

android/app/src/main/assets/fonts
  • antfill.ttf
  • antoutline.ttf

核心 代码:

import {
    
    IconOutline, OutlineGlyphMapType} from '@ant-design/icons-react-native';
import React from 'react';
import {
    
    TextProps} from 'react-native';
export type IconNames = OutlineGlyphMapType;
export interface IconProps extends TextProps {
    
    
  size?: 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | number;
  color?: string;
  name: IconNames;
}

export default class Icon extends React.Component<IconProps, any> {
    
    
  static defaultProps = {
    
    
    size: 'md',
  };
  static displayName = 'Icon';
  render() {
    
    
    const {
    
    size, color, name, ...rest} = this.props;
    const sizeMap: {
    
    [key: string]: number} = {
    
    
      xxs: 15,
      xs: 18,
      sm: 21,
      md: 22,
      lg: 36,
    };
    const fontSize = typeof size === 'string' ? sizeMap[size] : size;

    return (
      <IconOutline
        size={
    
    fontSize}
        color={
    
    color || '#cccccc'}
        name={
    
    name}
        {
    
    ...rest}
      />
    );
  }
}

运行测试

在这里插入图片描述
至此我没有使用Ant Design for React Native组件的情况下,也可以把我的常用的组件用起来了。

总结

经过这一翻的折腾,舒服了多了。本文只是提供一个思路。因为我比较常用的是icon组件和grid组件,其他的组件也可以根据这个思路来提取。只引用最需要的组件,就不会那么臃肿了。

示例代码下载

https://download.csdn.net/download/lxyoucan/59367460

特别说明,这个项目代码仅在安卓下测试了,iOS上跑的话,需要手动配置一下字体。

Acho que você gosta

Origin blog.csdn.net/lxyoucan/article/details/121809143
Recomendado
Clasificación