Introducción detallada al uso de la nueva versión de react-native 0.71 para desarrollar rápidamente proyectos de aplicaciones (ts+zustand+react-navigation+react-native-vector-icons)

1.Introducción al proyecto

Utilizando la nueva versión de reaccionar-nativo 0.71 para desarrollar rápidamente la aplicación, se realizaron de manera preliminar el inicio de sesión, la página de inicio, la configuración y algunos módulos de demostración, y se personalizaron algunos componentes comunes. Incluye casos simples de componentes de enrutamiento, componentes de cuadros de texto, componentes de celdas, componentes de botones, componentes de tablas y componentes de selección de ventanas emergentes. Estos componentes son las implementaciones más simples y están destinadas a que los amigos novatos las aprendan. Podrás ampliarlo más adelante según tus necesidades.

Este proyecto utiliza la versión relativamente nueva del marco rn (0.71) y se desarrolla utilizando el marco ts. La biblioteca de administración de estado no usa el reductor de reacción, pero usa Zustand: una biblioteca de administración de estado moderna y liviana (similar a Pinia en Vue).

 

2. Crea un proyecto

 Cree un proyecto nativo de reacción e instale las bibliotecas dependientes que necesitamos

1.npx react-native init birckdogApp --version 0.71.0
2.npm install zustand 
3.npm install @react-navigation/native 
4.npm install @react-navigation/native-stack
5.npm install @react-navigation/bottom-tabs
6.npm install react-native-screens react-native-safe-area-context 
7.npm install @react-native-async-storage/async-storage
8.npm install react-native-vector-icons --save
9.npm i --save-dev @types/react-native-vector-icons

2.1 Necesito cambiar el maven del que depende cada proyecto al almacén de Alibaba Cloud.

 2.2 Se debe hacer referencia a la biblioteca reaccionar-native-vector-icons en el archivo build.gradle del proyecto principal

aplicar desde: file("../../node_modules/react-native-vector-icons/fonts.gradle");

3. Página de inicio de sesión

 3.1 Utilice zustand para crear un objeto de gestión de estado UserInfo simple

Utilice el tipo para definir el tipo UserInfo y el tipo UserStoreInfo, y utilice create de zustand para crear un objeto de gestión de estado useUserInfo.

useUserInfo El objeto de usuario en la gestión de estado se utiliza para almacenar datos del usuario.

El método setUserInfos en la gestión de estado useUserInfo asigna un valor al objeto de usuario, (usuario: UserInfo | null) => Promise<void> indica que el parámetro del método es usuario, el tipo de parámetro es UserInfo y el parámetro puede estar vacío, y el El tipo de retorno del método es un objeto Promise de tipo nulo.

El método userInitialize en la administración del estado useUserInfo es cargar los datos almacenados en AsyncStorage en el objeto de usuario. Debido a que la operación de AsyncStorage es una operación asincrónica, se debe agregar async delante del método. En nuestro método, cargaremos la información del usuario cuando se inicie el programa principal de la aplicación, porque todos los objetos de administración de estado de zustand se perderán después de cerrar la aplicación.

import { create } from 'zustand';
import AsyncStorage from '@react-native-async-storage/async-storage';

type UserInfo = {
  id: string;
  account: string;
  userName: string;
  token: string;
};

type UserStoreInfo = {
  user: UserInfo | null;
  setUserInfos: (user: UserInfo | null) => Promise<void>;
  userInitialize: () => Promise<void>;
};

const useUserInfo = create<UserStoreInfo>((set) => ({
  user: null,
  setUserInfos: (user) => {
    return new  Promise<void>(async resolve =>  {
      try {
        // 将用户信息保存到本地存储
        await AsyncStorage.setItem('user', JSON.stringify(user));
        set({ user });
      } catch (error) {
        console.error('Failed to set user in AsyncStorage:', error);
      }
      resolve();
    });
  },
  userInitialize: async () => {
    return new  Promise<void>(async resolve =>  {
      try {
        // 从本地存储中获取用户信息
        const user = await AsyncStorage.getItem('user') as string;
        set({ user: JSON.parse(user) });
      } catch (error) {
        console.error('Failed to get user from AsyncStorage:', error);
      }
      resolve();
    });
  },
}));

export default useUserInfo;

3.2 Crear página de inicio de sesión

Usamos nuestro propio componente BdButton definido para la página de inicio de sesión. El uso de nuestros propios componentes encapsulados puede unificar mejor el estilo de la interfaz de usuario y simplificar el código. Explicaremos cómo personalizar los componentes más adelante.

import React, { useState } from 'react';
import { View, TextInput, StyleSheet } from 'react-native';
import useUserInfo from '../../../src/stores/userInfo';
import BdButton from '../../../src/components/bd-Button';

const LoginScreen = () => {
  const [account, setAccount] = useState('');
  const [password, setPassword] = useState('');
  const { setUserInfos } = useUserInfo();
  const handleLoginUser = () => {
    const newUser = {
      id: Date.now().toString(),
      account,
      userName:'测试',
      token: Date.now().toString(),
    };
    setUserInfos(newUser);
    setAccount('');
    setPassword('');
  };

  return (
    <View style={styles.container}>
      <View style={styles.loginContainer}>
        <TextInput
          style={styles.input}
          placeholder="账号"
          value={account}
          onChangeText={setAccount}
        />
        <TextInput
          style={styles.input}
          placeholder="密码"
          value={password}
          onChangeText={setPassword}
        />
        <BdButton
          style={styles.button}
          text="登录"
          onPress={handleLoginUser}
        />
      </View>
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F7F8FA',
  },
  loginContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom:200,
  },
  input: {
    width: '90%',
    height: 40,
    borderWidth: 1,
    borderColor: '#646566',
    marginBottom: 10,
    paddingHorizontal: 10,
  },
  button: {
    width: '90%',
  },
});
export default LoginScreen;

3.3 Lógica de inicio de sesión de juicio de entrada del programa

App.tsx es la entrada principal de nuestro programa. Aquí usamos el gancho useEffect para inicializar los datos del usuario cuando se inicia la aplicación.

StatusBar es un componente que controla la barra de estado de la aplicación. Aquí, el fondo de la barra de estado en la parte superior del teléfono está configurado en gris claro y el estilo de fuente en la barra de estado es modo oscuro.

Navigator es la ruta de nuestra página.

import React, { useState, useEffect } from 'react';
import { StatusBar } from 'react-native';
import useUserInfo from '../src/stores/userInfo';
import LoginScreen from '../src/views/login/index';
import Navigator from '../src/components/navigator';
import { BdStyleConfig } from '../src/theme/bd-styles';

const App = () => {
  const { user, userInitialize } = useUserInfo();
  const [isLoad, setIsLoad] = useState(true);
  useEffect(() => {
    userInitialize().then(()=>{
      setIsLoad(false);
    });
  },[userInitialize]);

  return (
    <>
     <StatusBar backgroundColor={BdStyleConfig.color_lightGrey} barStyle='dark-content' />
    { isLoad ? '' : (user?.token ? <Navigator /> : <LoginScreen />) }
    </>
  );
};
export default App;

4. Construir rutas

Utilice @react-navigation/bottom-tabs para crear la pestaña inferior del programa principal (página de inicio y configuración)

Utilice @react-navigation/native-stack para crear el enrutamiento interno de cada página de pestaña (la página de inicio tiene páginas de subenrutamiento, como estanterías de materiales y recibos de almacén)

import React from 'react';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import MyHomeScreen from '../../src/views/myHome/index';
import SettingScreen from '../../src/views/setting/index';
import MaterialListingScreen from '../../src/views/business//materialListing/index';
import WarehouseReceiptScreen from '../../src/views/business//warehouseReceipt/index';
import MaterialSearchScreen from '../../src/views/business//warehouseReceipt/materialSearch';
import PrintSettingScreen from '../../src/views/business//printSetting/index';
import { BdStyles, BdStyleConfig } from '../../src/theme/bd-styles';

const Tab = createBottomTabNavigator();

function HomeStack() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions = {({ route }) => ({
          tabBarIcon: ({ focused, color, size }) => {
            let iconName = '';
            
            if (route.name === 'Home') {
              iconName = focused ? 'home' : 'home-outline';
            } else if (route.name === 'Setting') {
              iconName = focused ? 'settings' : 'settings-outline';
            };
            
            return <Ionicons name={iconName} size={size} color={color} />;
          },

          tabBarActiveTintColor: BdStyleConfig.color_primary,
          tabBarInactiveTintColor: 'gray',
        })}
      >
        <Tab.Screen name="Home"  options={
   
   { headerShown:false, title:'首页' }} component={MyHomeStack} />
        <Tab.Screen name="Setting" options={
   
   { headerShown:false, title:'设置' }} component={SettingScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

const Stack = createNativeStackNavigator();

function MyHomeStack() {
  return (
   <Stack.Navigator screenOptions={
   
   {
      headerStyle: {
        backgroundColor: BdStyleConfig.color_lightGrey,
      },
      headerTintColor: '#000',
      headerTitleStyle: {
       color:'#000',
       fontSize:18,
      },
      headerTitleAlign: 'center', // 将标题居中
      animation: 'slide_from_right', // 通过animation属性设置动画效果
  }}>
    <Stack.Screen name="MyHome" options={
   
   { title:'首页' }}  component={MyHomeScreen} />
    <Stack.Screen name="MaterialListing" options={
   
   { title:'物料上架' }}  component={MaterialListingScreen} />
    <Stack.Screen name="WarehouseReceipt" options={
   
   { title:'仓库收料' }} component={WarehouseReceiptScreen} />
    <Stack.Screen name="MaterialSearch" options={
   
   { title:'收料查询' }} component={MaterialSearchScreen} />
    <Stack.Screen name="PrintSetting" options={
   
   { title:'打印设置' }} component={PrintSettingScreen} />
  </Stack.Navigator>
  );
}

export default function Navigator() {
    return (
        <HomeStack />
    );
}

5. Crea una página de inicio

import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { NavigationProp, ParamListBase } from '@react-navigation/native';
import { BdStyles, BdStyleConfig } from '../../../src/theme/bd-styles';

const MyHomeScreen = ({ navigation }: { navigation: NavigationProp<ParamListBase> }) => {
  const handleMenuPress = (menu:string) => {
    navigation.navigate(menu);
  };
  return (
    <View style={BdStyles.container}>
      <View style={styles.row}>
        <TouchableOpacity
          style={[styles.menuItem, styles.menuBorder]}
          onPress={() => handleMenuPress('WarehouseReceipt')}
        >
          <Ionicons name="archive-outline" size={30} color="#646566" />
          <Text style={styles.menuTitle}>仓库收料</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={[styles.menuItem, styles.menuBorder]}
          onPress={() => handleMenuPress('MaterialListing')}
        >
          <Ionicons name="arrow-up-circle-outline" size={30} color="#646566" />
          <Text style={styles.menuTitle}>物料上架</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={[styles.menuItem, styles.menuBorder]}
        >
          <Ionicons name="library-outline" size={30} color="#646566" />
          <Text style={styles.menuTitle}>工单拣料</Text>
        </TouchableOpacity>
      </View>
      /**其他菜单**/
  </View>
  );
};

const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
  },
  menuItem: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    paddingBottom:15,
    paddingTop:15,
    backgroundColor:BdStyleConfig.color_white,
  },
  menuBorder: {
    borderColor: '#ebedf0',
    borderWidth: 0.5,
  },
  menuTitle: {
    color: '#646566',
    marginTop: 5,
  },
});

export default MyHomeScreen;

6. Crear configuraciones

Aquí usamos el componente de celda personalizado BdCell

import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Alert } from 'react-native';
import useUserInfo from '../../../src/stores/userInfo';
import Ionicons from 'react-native-vector-icons/Ionicons';
import BdCell from '../../components/bd-cell';

const SettingScreen = () => {
  const { user, setUserInfos } = useUserInfo();

  const handleLoginOut = () => {
    Alert.alert(
      "消息",
      "是否确定退出登录!",
      [
        {
          text: "取消",
          onPress: () => console.log("Cancel Pressed"),
          style: "cancel"
        },
        { text: "确定", onPress: () =>  setUserInfos(null) }
      ]
    );
  };
  return (
    <View style={styles.container}>
      <TouchableOpacity style={styles.userInfoContainer}>
          <Ionicons name="person-circle" size={80} color="#c1c1c1" />
          <View style={
   
   { alignItems: 'center', justifyContent: 'center',}}>
            <Text style={
   
   { fontSize:25, color:'#000', fontWeight: 'bold', marginBottom:5 }}>{ user?.userName }</Text>
            <Text style={
   
   { fontSize:13, color:'#c1c1c1',paddingLeft:7 }}>欢迎您!</Text>
          </View>
      </TouchableOpacity>
      <View style={styles.listContainer}>
        <BdCell title="系统设置" style={styles.cellStyle} />
        <BdCell title="退出" onPress={handleLoginOut} />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor:'#F7F8FA',
  },
  userInfoContainer: {
    flexDirection: 'row',
    backgroundColor:'#fff',
    padding:10,
  },
  listContainer: {
    paddingTop:10,
  },
  cellStyle:{
    borderBottomColor:'#F7F8FA',
    borderBottomWidth:1,
  }
});

export default SettingScreen;

7. Desarrollo de componentes personalizados

7.1 Componente del botón BdButton

Para el componente de botón personalizado BdButton, primero definimos cuántas propiedades contiene el tipo ButtonProps para el componente. La propiedad de estilo nos permite reescribir el estilo del componente. El "en estilo" es un operador de concatenación opcional. La definición aquí indica que este parámetro Puede estar vacío o no pasar.

import React from 'react';
import { TouchableOpacity, Text, StyleSheet, ViewStyle } from 'react-native';
import { BdStyles, BdStyleConfig } from '../../src/theme/bd-styles';

interface ButtonProps {
    style?: ViewStyle;
    onPress?: () => void;
    text: string;
}

const BdButton: React.FC<ButtonProps> = ({ style, onPress, text }) => {
  return (
    <TouchableOpacity style={[styles.button, style]} onPress={onPress}>
      <Text style={styles.text}>{text}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  button: {
    backgroundColor:BdStyleConfig.color_primary,
    padding: 10,
    borderRadius: 5,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    color: 'white',
    fontWeight: 'bold',
  },
});

export default BdButton;

7.2 Componente de la tabla BdTable

El uso simple del componente de tabla, solo necesitamos pasar los atributos de datos y columnas al componente para generar nuestra tabla.

const tableData = [
  { id: '1001', count: 5, total: 15, remainCount: 3 },
  { id: '1002', count: 7, total: 17, remainCount: 2 },
  { id: '1003', count: 3, total: 12, remainCount: 1 },
  // 其他数据...
]

const tableColumns:BdTablePropsColumn[] = [
  { field: 'id',  title: '料号', align: 'center', },
  { field: 'count',  title: '件数', align: 'center', },
  { field: 'total',  title: '总数量', align: 'center', },
  { field: 'remainCount',  title: '剩余数量', align: 'center', },
]

const MaterialSearchScreen = () => {
  return (
    <View style={BdStyles.container}>
      <BdTable
        data={tableData}
        columns={tableColumns}
      />
    </View>
  );
};

Código de componente de tabla

import React from 'react';
import { View, Text, VirtualizedList, StyleSheet, TouchableOpacity } from 'react-native';

export interface BdTableProps {
  data: any[];
  columns: BdTablePropsColumn[];
  onClickRow?: ((item:any) => void) | undefined;
  hideHeader?: boolean;
}

export interface BdTablePropsColumn {
  field: string,
  title: string,
  align: string,
}

const BdTable: React.FC<BdTableProps> = ({ columns, data, onClickRow, hideHeader }) => {
  const renderItem = (item:any) => (
    <TouchableOpacity key={new Date().getTime()} style={styles.row} onPress={() =>{ onClickRow?onClickRow(item.item):'' }}>
      {columns.map((column) => (
        <Text style={styles.cell}>{item.item[column.field]}</Text>
      ))}
    </TouchableOpacity>
  );

  const tableHeader = () => (
    <View style={styles.row}>
      {columns.map((column) => (
         <Text key={column.field}  style={styles.headerCell}>{column.title}</Text>
      ))}
    </View>
  );

  const keyExtractor = (item:any) => item.id?item.id.toString():new Date().getTime();
  const getItemCount = () => data.length;
  const getItem = (data: [], index: number) => data[index];
  return (
    <VirtualizedList
      data={data}
      renderItem={renderItem}
      keyExtractor={keyExtractor}
      ListHeaderComponent={ !hideHeader?tableHeader:undefined }
      getItemCount={getItemCount}
      getItem={getItem}
    />
  );
};
const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
    justifyContent: 'space-between',

    backgroundColor:'#fff',
  },
  cell: {
    flex: 1,
    textAlign: 'center',
    borderColor: '#e4eaec',
    borderWidth:1,
    padding:4,
  },
  headerCell: {
    flex: 1,
    textAlign: 'center',
    borderColor: '#e4eaec',
    borderWidth:1,
    fontWeight:'bold',
    padding:4,
  },
});

export default BdTable;

8.Estructura del proyecto

Supongo que te gusta

Origin blog.csdn.net/qq243348167/article/details/131795062
Recomendado
Clasificación