美文网首页
ReactNative 入门

ReactNative 入门

作者: YM雨蒙 | 来源:发表于2022-04-22 12:00 被阅读0次

    最近公司有移动端Android 的项目, 使用的技术栈是 ReactNative, 准备学习一下, 了解一下技术栈, 首先需要做的就是搭建开发环境, 可以自己选择的电脑系统和安卓/ios移动端

    准备 Android 开发环境

    1. node => v17.8.0
    2. yarn => 1.22.17
    3. javac => 11.0.14.1
    4. Android Studio
    5. Android 手机 => 打开开发者模式 => usb调试 (不使用模拟机)

    创建第一个项目

    # 不要单独使用常见的关键字作为项目名
    # 不要在目录、文件名中使用中文、空格等特殊符号
    npx react-native init firstapp
    
    # --template 使用模板
    npx react-native init AwesomeTSProject --template react-native-template-typescript
    

    运行生成 firstapp 目录解析

    .
    ├── App.js // index.js 引用了 App.js 显示内容
    ├── Gemfile // 这个是 ruby 的包管理, 类似 package.json
    ├── Gemfile.lock // 类似于前端的 yarn.lock
    ├── README.md
    ├── __tests__ // 可以写测试
    ├── android // 原生 Android 工程文件夹
    ├── app.json // 可以设置 app 的名字 配置项
    ├── babel.config.js // 配置 babel
    ├── index.js // RN移动端项目的入口
    ├── ios // 原生 ios 工程文件夹
    ├── metro.config.js // metro是一种支持ReactNative的打包工具配置
    ├── node_modules
    ├── package.json
    └── yarn.lock
    

    启动项目

    1. 查看我们的设备, 图片显示我们连接了一台 android 手机
    查看我们运行的设备
    1. 启动项目
    # 查看 package.json
    yarn android
    or
    yarn react-native run-android
    
    项目默认首页
    1. 我们可以看到上面项目启动以后有一个默认的首页,

    分析代码

    1. 入口 index.js
    // AppRegistry 是所有 React Native 应用的 JS 入口
    import {AppRegistry} from 'react-native';
    import App from './App';
    import {name as appName} from './app.json';
    
    // 根组件通过 AppRegistry.registerComponent 方法注册自己
    // 原生系统才可以加载应用的代码包并且在启动完成之后通过调用AppRegistry.runApplication来真正运行应用
    AppRegistry.registerComponent(appName, () => App);
    
    1. index.js 引用了 App.js, 里面的内容比较多, 改成我们熟悉的 Hello World
    // 引用React  react-native 原生组件
    import React from 'react';
    import {Text, View} from 'react-native';
    
    const App = () => {
      return (
        <View>
          <Text>Hello World!</Text>
        </View>
      );
    };
    
    export default App;
    
    1. 玩一下, 删除 App.js 修改入口为 android_app/app.js
      • 创建 android_app 文件夹
      • 创建 android_app/app.js
      • 修改 index.js
    import {AppRegistry} from 'react-native';
    import App from './android_app/app'; // 修改引用
    import {name as appName} from './app.json';
    
    AppRegistry.registerComponent(appName, () => App);
    
    • 更新目录
    .
    ├── Gemfile
    ├── Gemfile.lock
    ├── README.md
    ├── __tests__
    ├── android
    ├── android_app // 新建的目录
    │   └── app.js // 入口指向
    ├── app.json
    ├── babel.config.js
    ├── index.js
    ├── ios
    ├── metro.config.js
    ├── node_modules
    ├── package.json
    └── yarn.lock
    

    创建自己的文件夹

    我们上面的代码创建了 android_app 文件目录, 这里就作为我们开发 Android 项目的文件夹

    • 可以创建 pages/ 作为我们不同页面的目录
    • 可以创建 components/ 作为我们项目中组件目录
    • 可以创建其它目录, 就像平常的前端开发一样

    调试代码

    运行代码如何调试呢?

    1. 首先我们启动项目的时候,会打开一个 Metro 命令行工具

      metro.png
    2. 在手机上我们可以看到打开了一个 development menu

      debug.jpg
    3. 选中 Debug 会在我们的电脑上打开一个 浏览器 Tab 页, 打开开发者调试工具, 既可以调试了

    对比学习法, 写一个 TodoList

    对比就是: 用我们熟悉的前端 React 写法 来修改为 ReactNative 写法, 下面我们在脑子里想象一下写一个我们熟悉的 TodoList, 你用 React 怎么写, 如果换成RN 环境我们该怎么写

    todo 基本样式, 包含新增和删除
    1. 上面的图片就是我在 android 上写的一个 todo, 看一下代码对比一下和我们开发 web 有什么不同
      • 下面的代码使用的编程语言也是 React hook, 也是 JSX 语言
      • 不同点就是引用了 react-native 的一些原生组件, 没有使用 div p spanhtml
      • 下面的 View 标签 可以当做 div 看, Text 标签 当做 span, TextInput 当做 input,
      • 其实这些标签我们也可以当做我们引用了 react-native 组件库 在使用
      • 还有一个比较大的不同 css 样式, 这里使用的是 对象写法, 这个需要我们熟悉一下
    // 找到我们的 anndroid_app/app.js
    
    import React, {useState} from 'react';
    import {
      Text,
      View,
      TextInput,
      TouchableHighlight,
      TouchableOpacity,
    } from 'react-native';
    import styles from './style.js';
    
    const App = () => {
      const [input, setInput] = useState('');
      const [list, setList] = useState([]);
    
      const onPressAddTodo = () => {
        setList([...list, input]);
      };
    
      const onPressDeleteItem = index => {
        const copy = [...list];
        copy.splice(index, 1);
        setList(copy);
      };
    
      return (
        <View style={styles.todo_wrap}>
          <View style={styles.input_wrap}>
            {/* 输入框 */}
            <TextInput
              style={styles.input}
              onChangeText={text => setInput(text)}
              value={input}
            />
            {/* 按钮 */}
            <TouchableHighlight onPress={onPressAddTodo}>
              <View style={styles.button}>
                <Text>新增todo</Text>
              </View>
            </TouchableHighlight>
          </View>
          {/* todo列表 */}
          <View style={styles.list_wrap}>
            {list.map((item, index) => {
              return (
                <View style={styles.item} key={index}>
                  <Text>{item}</Text>
                  <TouchableOpacity
                    style={styles.button}
                    onPress={() => onPressDeleteItem(index)}>
                    <Text>删除{index}</Text>
                  </TouchableOpacity>
                </View>
              );
            })}
          </View>
        </View>
      );
    };
    
    export default App;
    
    
    // android_app/styles.js
    
    import {StyleSheet} from 'react-native';
    
    const styles = StyleSheet.create({
      todo_wrap: {
        flex: 1,
        borderWidth: 5,
        borderStyle: 'solid',
        borderColor: 'pink',
        margin: 10,
      },
      input_wrap: {
        marginTop: 20,
      },
      input: {
        height: 40,
        borderColor: 'gray',
        borderWidth: 1,
      },
      button: {
        marginTop: 20,
        alignItems: 'center',
        backgroundColor: 'dodgerblue',
        padding: 10,
      },
      list_wrap: {
        borderWidth: 3,
        borderStyle: 'solid',
        borderColor: 'red',
        marginTop: 10,
      },
      item: {
        flexDirection: 'row',
        justifyContent: 'space-between',
        alignItems: 'center',
        paddingTop: 10,
        paddingBottom: 10,
        fontSize: 16,
        borderBottomWidth: 2,
        borderBottomColor: '#ccc',
      },
    });
    
    export default styles;
    

    看了上面的代码, 我们基本可以对 React Native 有了一个基本的了解, 下面我们来看一下 React Native 一些常用的 组件和API , 简单做个总结, 可以看官方文档

    React-Native 常用组件

    ReactNative 虽然使用的是 react 技术栈, 但 JS 将 React 基础抽象组件渲染为原生平台UI组件, 有一些自己独有的 元素api

    基础组件

    1. Text: 显示文本内容的组件, 支持文本和样式的嵌套以及触摸事件处理
    <Text style={styles.baseText} onPress={onPress} selectable>
    
    1. TextInput: 输入框组件, 支持自动拼写修复, 自动大小写切换, 展位默认字符以及多种键盘设置
    <TextInput
      onChangeText={(text) => onChangeText(text)}
      value={value}
      autoCorrect
      {...restProps}
    />
    
    1. Image: 图片展示组件, 支持多种类型图片的展示, 包括网络图片, 静态资源, 本地图片等
    <Image
      style={styles.tinyLogo}
      source={{
        uri: "https://reactnative.dev/img/tiny_logo.png",
      }}
      width={150}
      height={150}
      blurRadius={1}
    />
    
    1. ActivityIndicator: 加载指示器组件(loading)
    <ActivityIndicator animating={animating} />
    
    1. Switch: 状态切换组件(开关)
    <Switch
      trackColor={{ false: "#767577", true: "#81b0ff" }}
      thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
      onValueChange={toggleSwitch}
      value={isEnabled}
    />
    

    容器组件

    1. View: 容器组件, 支持 Flexbox 布局, 样式, 触摸事件和处理一些无障碍功能, 可以放到其它容器组件, 也可以包含任意多个子组件
    <View style={styles.centeredView}>
      <View style={styles.modalView}>
        <Text style={styles.modalText}>Hello World!</Text>
      </View>
    </View>
    
    1. ScrollView: 一个通用的滚动容器组件, 支持垂直和水平两个方向上的滚动, 必须有一个确定的高度才能正常工作

    2. Touchable[Opacity | Highlight | WithoutFeedback | NativeFeedback]: 透明触摸/高亮触摸/无反馈/水波纹 => 用于封装视图,使其可以正确响应触摸操作

    <TouchableOpacity onPress={press}>
      <Text style={{ color: "red" }}>跳转到下一页面</Text>
    </TouchableOpacity>
    

    列表组件

    1. VirtualizedList:列表组件: 文档地址

      • 一般来说: 除非特殊的性能要求, 不建议直接使用, 因为 VirtualizedList 是一个抽象组件, 实际开发中, 使用 FlatList 和 SectionList 组件即可满足开发需求, 它们基于 VirtualizedList 组件扩展的
    2. FlatList:适用于加载长列表数据, 高性能的简单列表数据

    <FlatList
      data={DATA}
      renderItem={renderItem}
      keyExtractor={(item) => item.id} // key
      // 分割线 => borderBottom 或者  ItemSeparatorComponent
    
      // 下拉刷新/上拉加载更多
      refreshing // 是否处于正在刷新的状态
      onRefresh // 开始刷新事件, 发起接口请求
      onEndReached // 上拉加载更多
      onEndReachedThreshold={0} // 当距离内容最底部还有多远时触发onEndReached回调, 此参数是一个比值而非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发
    />
    
    1. SectionList: 高性能分组列表组件, 不同于 FlatList, SectionList 主要用于开发列表分组, 吸顶悬浮等功能
    const DATA = [
      {title: '', data: []}
    ]
    <SectionList
      sections={DATA}
      keyExtractor={(item, index) => item + index}
      renderItem={({ item }) => <Item title={item} />} // 渲染每一个列表视图
      renderSectionHeader={({ section: { title } }) => ( // 渲染每一个 section中的每一个列表项视图
        <Text style={styles.header}>{title}</Text>
      )}
    />
    

    平台组件

    适用于 Android 和 Ios 自己平台的组件, 查看文档

    ReactNative 常用 API

    组件是构成页面视图的基本元素, API 就是构成功能模块的基本元素

    基础 API

    1. AppRegistry: AppRegistry 是所有 React Native 应用的 JS 入口。应用的根组件应当通过 AppRegistry.registerComponent 方法注册自己
    AppRegistry.registerComponent(appName, () => App);
    
    1. AppState:告诉你应用当前是在前台还是在后台,并且能在状态变化的时候通知你
    active: 应用正在前台运行;
    background: (在后台运行) => 在别的应用;
    停留在桌面;
    inactive: 正在前后台的切换过程中;
    
    useEffect(() => {
      AppState.addEventListener("change", _handleAppStateChange);
    
      return () => {
        AppState.removeEventListener("change", _handleAppStateChange);
      };
    }, []);
    
    AppState.currentState;
    
    1. NetInfo: 用于获取手机联网状态的 API
    // none: 离线;
    // wifi: wifi联网;
    // cellular: 通过蜂窝数据联网
    // unkonwn: 联网状态异常
    NetInfo.getConnectionInfo().then(); // 获取手机联网状态
    
    NetInfo.addEventListener(name, handler); // 监听网络状态
    NetInfo.isConnectionExpensive(); // 连接是否收费
    
    1. AsyncStorage: 异步 持久化数据存储 API, 它以键值对方式保存数据 => 全局的, 先封装后再使用
    // 常用的:
    getItem(): 根据键值获取数据, 结果返回回调函数
    setItem(): 保存值
    removeItem(): 删除
    mergeItem():  合并已有的值和新的值
    clear(): 清除
    
    1. DeviceEventEmitter:发布订阅模式, 在两个相互独立的组件之间通信使用, 类似 Vue 的 EventBus
    DeviceEventEmitter.addListener("我要吃饭", (草莓) => {
      console.log(`我要吃${草莓}`);
    });
    
    DeviceEventEmitter.remove();
    
    DeviceEventEmitter.emit("我要吃饭", "草莓");
    

    屏幕相关 API

    1. Dimensions: 用于获取设备屏幕的宽高。
    Dimensions.get("window");
    
    const windowWidth = Dimensions.get("window").width;
    const windowHeight = Dimensions.get("window").height;
    
    1. PixelRatio:取到设备的像素密度和字体缩放比, 设备像素: 物理像素/设备独立像素
      • 例如: ip4 => 屏幕物理像素 640, 独立像素 320, PixelRatio 为 2
      • RN 开发使用的尺寸单位是 pt, 由于移动设备像素密度不一样, 1pt 对应的像素也不一样
      • 屏幕分辨率 = 屏幕宽高 * 屏幕像素密度
    get() => 1: mdpi android devices; 1.5: hdpi android devices; ... // 设备的像素密度
    getFontScale() // 字体大小缩放比例
    

    动画 API

    1. requestAmimationFrame: 帧动画, 通过不断改变组件的状态来实现动画效果
    2. LayoutAnimation: 布局动画, 当布局发生改变时的动画模块 布局动画文档
    3. Animated: 侧重于输入和输出之间的声明性关系,以及两者之间的可配置变换,此外还提供了简单的 start/stop 方法来控制基于时间的动画执行

    平台 API

    1. BackHandler:用于监听 Android 设备返回事件的 API
    // 示例: android 退出应用
    BackHandler.addEventListener("hardwareBackPress", () => {
      console.log("再按一次退出应用");
      BackHandler.exitApp();
    });
    BackHandler.removeEventListener("hardwareBackPress", () => {});
    
    1. PermissionsAndroid: 访问 Android M(也就是 6.0)开始提供的权限模型, 仅对 Android 平台有效
    CAMERA: (相机权限) => android.permission.CAMERA;
    READ_CALENDAR: (日历) => android.permission.READ_CALENDAR;
    ...等等
    
    check() // 检测用户是否授权过某个动态权限
    request() // 弹出提示框向用户请求某项动态权限
    requestMultiple() // 多个权限
    

    第三方库

    1. NativeBase: 一款优秀的 RN 组件库,提供了丰富的第三方组件
    yarn add native-base
    
    1. react-native-elements: 也是一个常见的 ReactNative 组件库
    yarn add @rneui/themed @rneui/base
    yarn add react-native-vector-icons
    
    1. react-navigation
      • 一个完整的移动应用有多个页面组成, 页面之间跳转, 使用 react-navigation
      • 中文文档
      • 英文文档
    // 支持三种类型的导航器
    StackNavigator: 包含导航栏的页面导航组件
    TabNavigator: 底部展示 TabBar 的页面导航组件
    DrawerNavigator: 实现侧边栏抽屉页面的导航组件
    
    1. react-native-snap-carousel: 一个轮播组件库
    <Carousel
      data={this.state.entries} // 数据源
      renderItem={this._renderItem} // 渲染单个视图
      sliderWidth={sliderWidth} // 循环容器的宽度
      itemWidth={itemWidth} // 子元素的宽度
    />
    
    1. react-native-image-picker: 拍照和相册管理库, 实现拍照和图片选取功能

    2. react-native-video: 视频播放组件库

    相关文章

      网友评论

          本文标题:ReactNative 入门

          本文链接:https://www.haomeiwen.com/subject/urlwertx.html