React Native 基于Expo开发(二)启动页

4,134 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

什么是启动页?

打开一个app,会有一个类似欢迎界面的东西,这个玩意儿就是启动页。(也有不少app在打开的时候会看到广告,倒计时的那种效果,这个是后面有用到再说吧)

  • 在android里面,叫做SplashActivity
  • 在iOS里面,叫做LaunchScreen

启动页配置

使用expo搭建的项目,在项目的根目录中,找到app.json。第一次创建的项目,里面的内容大致长下面这样。

{
  "name": "my-project",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "expo": "~45.0.0",
    "expo-status-bar": "~1.3.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-native": "0.68.2",
    "react-native-web": "0.17.7"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9"
  },
  "private": true
}

添加下面这几个参数进去

    "slug": "my-project", // 项目publish之后,访问的url的后缀
    "orientation": "portrait", // app在移动端可以支持的方向,我这边只支持竖屏
    "icon": "./assets/icon.png", // app的图标,放到项目的assets文件夹下
    "splash": { // 这个就是启动页的配置
      "image": "./assets/launch.png", // 启动图片,放到项目的assets文件夹下
      "resizeMode": "cover" // 图片的模式,值一定要设置cover,如果设置contain的话,在andriod机型上会有白边
    },

这个时候再启动项目,你会发现你刚刚配置的启动图片就可以看到了,时间很短,大概从启动到消失估计也就1~2S时间。

启动页消失后,如果选择我们想要展示的第一个界面

大部分的app在启动页消失后,会根据是否登录过,来决定进入登录页还是主页。至少我这个app是这个逻辑。实际上,目前这个启动页,如果你不做任何代码上的限制,他会在一会就自动消失,然后展示你默认的第一个返回的界面。如何在启动页消失的时候进入我们想要进入的界面,而且如何保证第一个界面准备好显示到用户面前之前(可能会下载字体,数据请求的耗时操作),启动页不消失?

这里需要安装SplashScreen,这个是由expo官方提供的一个包

expo install expo-splash-screen

然后选择界面的逻辑代码,需要写在项目的根目录的App.js文件里面,React Native项目第一次启动就会执行App.js里面的代码。

贴出我项目里面的代码,可能再写法上不够官方的好看,但是功能能达到。

import AsyncStorage from '@react-native-async-storage/async-storage'; // 异步存取的三方工具
import * as SplashScreen from 'expo-splash-screen'; // 控制启动页的包
import React, { useEffect, useState } from 'react';
import { RootSiblingParent } from 'react-native-root-siblings'; // 背景渐变的包,可以忽略

import { customerInfo } from './api/user/list';
import MainStackScreen from './navigation/MainStackScreen';
const TOKEN_KEY = 'AUTH_TOKEN';

export default function App() {
  const [appIsReady, setAppIsReady] = useState(false);
  const [root, setRoot] = useState();
  useEffect(() => {
    SplashScreen.preventAutoHideAsync(); // 保证项目启动后,系统启动页一直显示
    chooseScreen();
  }, []);
  /**
   * 选择初始页面
   */
  const chooseScreen = async () => {
    const token = await AsyncStorage.getItem(TOKEN_KEY);
    if (token && token.length > 0) {
      getUserInfo();
    } else {
      setRoot('LaunchScreen'); // 登录页
      setAppIsReady(true);
    }
  };
  /**
   *  发送请求,判断token是否过期,决定进入登录页还是主页
   */
  const getUserInfo = () => {
    customerInfo()
      .then((res) => {
        setRoot('Tab'); // 主页
      })
      .catch(() => {
        setRoot('LaunchScreen'); // 登录页
      })
      .finally(() => {
        setAppIsReady(true);
      });
  };
  if (!appIsReady) {
    return null;
  } else {
    SplashScreen.hideAsync(); // 系统启动页消失(需要确保需要展示的界面已经准备好)
  }
  return (
    <RootSiblingParent>
      <MainStackScreen root={root} />
    </RootSiblingParent>
  );
}

这样就可以根据你想要的逻辑,来决定进入你想要进入的界面。 重点是 SplashScreen.preventAutoHideAsync(); SplashScreen.hideAsync();这两句,控制启动页的一直显示和何时消失。

溜了,明天说说界面的路由和导航栏,有些项目用到了tabbar(底部导航栏)。这个在React Native的项目里面尤为重要,也是没有接触过移动端开发的前端同学不理解的一块地方。

欢迎评论,一起踩坑