React Native基础

目录

一、创建项目

二、组件介绍

2.1、Text、View和Image组件

2.2、文件式导航(Link)

2.3、堆栈导航(Stack)

2.4、浅色与深色主题

2.5、主题化UI组件

2.6、路由分组与嵌套布局

2.7、Pressable组件

2.8、标签栏导航(Tabs)

2.9、安全区域适配(SafeAreaView)

一、创建项目

Expo官网:Expo Documentation (中文官网:教程:介绍 - Expo 中文网
创建一个文件夹,在VS Code的终端下输入命令:

**npx create-expo-app@latest --template blank ./**创建出一个空白模板的app

在英文官网首页点击Set up your environment - Expo Documentation

设置路由:Install Expo Router - Expo Documentation

二、组件介绍

2.1、Text、View和Image组件

效果展示:

javascript 复制代码
import { StyleSheet, Text, View, Image } from "react-native";
import Logo from "../assets/system.png";
export default function Page() {
  return (
    <View style={styles.container}>
      {/* 文本 */}
      <Text style={styles.title}>The Number 1</Text>
      {/* 内联样式 */}
      <Text style={{ marginTop: 10 }}>Welcome to Expo</Text>
      {/* 外部样式+内联样式 */}
      <Text style={[styles.title,{color:'gold'}]}>Reading this app</Text>
      {/* 图片 */}
      <Image style={styles.img} source={Logo} />
    </View>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "skyblue",
    alignItems: "center",
    justifyContent: "center",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
  },
  img: {
    borderRadius: "50%",
    marginVertical: 10,
  },
});

2.2、文件式导航(Link)

javascript 复制代码
import { Link } from "expo-router";
{/* 跳转 相当于HTML中的a标签 */}
<Link href="/about">跳转到about页面</Link>

2.3、堆栈导航(Stack)

为了产生页面的返回键和页面标题,前提:在app文件夹下建立_layout.jsx文件。

javascript 复制代码
import { Stack } from "expo-router";
const RootLayout = () => {
  return (
    <Stack
      screenOptions={{
        headerStyle: { backgroundColor: "#ddd" },
        headerTintColor: "#333",
      }}
    >
      <Stack.Screen name="index" options={{title: "Home"}}/>
      <Stack.Screen name="about" options={{title: "About"}}/>
      <Stack.Screen name="contact" options={{title: "Contact"}}/>
    </Stack>
  );
};
export default RootLayout;
// 如果第一步安装路由启动失败,加上_layout.jsx这个文件
// 可以重新安装依赖:rm -rf node_modules package-lock.json  npm install
// 想在web端查看页面:npx expo install react-dom react-native-web
// 再重新运行:npx expo start

2.4、浅色与深色主题

javascript 复制代码
import { useColorScheme } from "react-native";
import { Colors } from "../constants/Color";
import { StatusBar } from "expo-status-bar";
const RootLayout = () => {
  const colorScheme = useColorScheme();
  const theme = Colors[colorScheme] ?? Colors.light;
  return (
    <>
      <StatusBar value="auto" />
    </>
  );
};

2.5、主题化UI组件

以View为例:

javascript 复制代码
import { View, useColorScheme } from "react-native";
import {Colors} from "../constants/Color";
const ThemeView = ({ style, children, ...props }) => {
  const colorScheme = useColorScheme();
  const theme = Colors[colorScheme] ?? Colors.light;
  return (
    <View style={[style, { backgroundColor: theme.background }]} {...props}>
      {children}
    </View>
  );
};
export default ThemeView;

其实可以自己选组件库:

React Native Elements、 React Native PaperUI Kitten的文档如下(兼容IOS和安卓,后面两个可以搭配使用):

Overview | React Native Elements

ActivityIndicator | React Native Paper

UI Kitten - React Native Components

2.6、路由分组与嵌套布局

路由分组:将功能相关的路由归类,统一管理配置(如认证路由和主应用路由分离)

在app文件夹下再建一个文件夹,命名时用()括起来,此时页面title会变为"(auth/login)",此时想要取消页面的Header显示,则需要在(auth)文件夹下再建立一个_layout.jsx

javascript 复制代码
import { Stack } from "expo-router";
import { StatusBar } from "expo-status-bar";
const AuthLayout = () => {
  return (
    <>
      <StatusBar value="auto" />
      <Stack
        screenOptions={{
          headerShown: false,
          animation: "none",
        }}
      ></Stack>
    </>
  );
};
export default AuthLayout;

在RootLayout.jsx里

javascript 复制代码
<Stack.Screen name="(auth)" options={{headerShown: false}}/>

或者使用createNativeStackNavigator 分组

javascript 复制代码
// App.js
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const AuthStack = createNativeStackNavigator();
const MainStack = createNativeStackNavigator();
function AuthGroup() {
  return (
    <AuthStack.Navigator>
      <AuthStack.Screen name="Login" component={LoginScreen} />
      <AuthStack.Screen name="Register" component={RegisterScreen} />
    </AuthStack.Navigator>
  );
}
function MainGroup() {
  return (
    <MainStack.Navigator>
      <MainStack.Screen name="Home" component={HomeScreen} />
      <MainStack.Screen name="Profile" component={ProfileScreen} />
    </MainStack.Navigator>
  );
}
// 根导航器整合分组
const RootStack = createNativeStackNavigator();
function App() {
  return (
    <NavigationContainer>
      <RootStack.Navigator>
        <RootStack.Screen 
          name="Auth" 
          component={AuthGroup} 
          options={{ headerShown: false }}
        />
        <RootStack.Screen 
          name="Main" 
          component={MainGroup} 
          options={{ headerShown: false }}
        />
      </RootStack.Navigator>
    </NavigationContainer>
  );
}

拓展:

  1. 路由参数传递
javascript 复制代码
// 父路由传递参数给子路由
<Stack.Screen 
  name="Profile" 
  component={ProfileScreen}
  initialParams={{ userId: 123 }}
/>

// 子路由获取参数
function ProfileScreen({ route }) {
  const { userId } = route.params;
}
  1. 统一导航选项
javascript 复制代码
// 分组统一配置
<Stack.Navigator
  screenOptions={{
    headerStyle: { backgroundColor: '#4CAF50' },
    headerTintColor: 'white'
  }}
>
  {/* 所有子路由继承此样式 */}
</Stack.Navigator>

3、动态隐藏Header:headerShown: false

2.7、Pressable组件

用于检测各种按压交互(点击、长按等)

自定义组件ThemeBtn.jsx:

javascript 复制代码
import { StyleSheet, Pressable } from "react-native";
const ThemeBtn = ({ style, ...props }) => {
  return (
    <Pressable
      style={({ pressed }) => [
        styles.button,
        pressed && styles.buttonPressed,
        style,
      ]}
      {...props}
    />
  );
};
export default ThemeBtn;
const styles = StyleSheet.create({
  button: {
    padding: 18,
    marginVertical: 10,
    borderRadius: 6,
    backgroundColor: "#6849a7",
  },
  buttonPressed: {
    opacity: 0.5,
  },
});

父组件引用

javascript 复制代码
import ThemeBtn from "../../components/ThemeBtn";
const Login = () => {
  const handleSubmit = () => {
    console.log("submit");
  };
  return (
    <View>
      <ThemeBtn onPress={handleSubmit}>
        <Text style={{ color: "#f2f2f2", textAlign: "center" }}>Press Me</Text>
      </ThemeBtn>
    </View>
  );
};
export default Login;

列表项按压效果

javascript 复制代码
function ListItem({ item }) {
  return (
    <Pressable
      onPress={() => navigate('Detail', { id: item.id })}
      style={({ pressed }) => ({
        padding: 16,
        backgroundColor: pressed ? '#f0f0f0' : 'white',
      })}
    >
      <Text>{item.name}</Text>
    </Pressable>
  );
}

2.8、标签栏导航(Tabs)

建立(dashboard)文件夹,分别建立三个.jsx文件:profile、books、create

javascript 复制代码
import { Tabs } from "expo-router";
import { useColorScheme } from "react-native";
import { Colors } from "../../constants/Color";
// 下载图标 npm i @expo/vector-icons , 默认自带
import { Ionicons } from "@expo/vector-icons";
const DashboardLayout = () => {
  const colorScheme = useColorScheme();
  const theme = colorScheme === "dark" ? Colors.dark : Colors.light;
  return (
    <Tabs
      screenOptions={{
        headerShown: false,
        tabBarStyle: {
          backgroundColor: theme.navBackground,
          paddingTop: theme.iconColor,
          height: 90,
        },
        tabBarActiveTintColor: theme.iconColorFocused,
        tabBarInactiveTintColor: theme.iconColor,
      }}
    >
      {/* 自定义底部导航栏标题和图标 */}
      <Tabs.Screen
        name="profile"
        options={{
          title: "Profile",
          tabBarIcon: ({ focused }) => (
            <Ionicons
              name={focused ? "person" : "person-outline"}
              size={24}
              color={focused ? theme.iconColorFocused : theme.iconColor}
            />
          ),
        }}
      />
      <Tabs.Screen name="books" options={{ title: "Books" }} />
      <Tabs.Screen name="create" options={{ title: "Create" }} />
    </Tabs>
  );
};
export default DashboardLayout;

2.9、安全区域适配(SafeAreaView)

复制代码
SafeAreaView:直接包裹当前页面,但是无法灵活控制具体哪一侧需要安全边距,所以选择以下HOOk
useSafeAreaInsets() :可以手动获取安全区域的 top、bottom、left、right 值,并应用到样式中
javascript 复制代码
import { View, useColorScheme } from "react-native";
import { Colors } from "../constants/Color";
import { useSafeAreaInsets } from "react-native-safe-area-context";
const ThemeView = ({ style, safe = false, ...props }) => {
  const colorScheme = useColorScheme();
  const theme = Colors[colorScheme] ?? Colors.light;
  if (!safe)
    return (
      <View style={[style, { backgroundColor: theme.background }]} {...props} />
    );
  const insets = useSafeAreaInsets();
  return (
    <View
      style={[
        style,
        {
          backgroundColor: theme.background,
          paddingTop: insets.top,     // 避开刘海
          paddingBottom: insets.bottom, // 避开底部横条
        },
      ]}
      {...props}
    />
  );
};
export default ThemeView;
相关推荐
csj5010 小时前
前端基础之《React(10)—JSX语法》
前端·react.js
文阿花10 小时前
大屏实现方案之-Echarts
前端·javascript·echarts
朝阳3910 小时前
React 19 开发规范
前端·react.js·前端框架
包子源10 小时前
浏览器 ffmpeg.wasm 视频压缩:Next.js 静态站集成完整指南
javascript·ffmpeg·wasm
前端毕业班11 小时前
uniapp 实现微信小程序自定义 tabBar
前端·javascript·vue.js
暗不需求11 小时前
React 闭包陷阱:从现象到原理,一篇搞懂
前端·react.js·面试
之歆11 小时前
Day18_JavaScript高级核心:原型链、继承与事件循环机制深度解析(下)
前端·javascript·css
meilindehuzi_a11 小时前
javascript 对象全知识解析《JavaScript 语言精粹》深度解析:第 3 章“对象”核心机制与避坑指南
开发语言·javascript
LinDaiDai_霖呆呆11 小时前
呆老师亲授前端转全栈+AI 开发的学习图谱
前端·javascript·node.js