总是应该认识一些基本概念
原生组件
在 rn 中不可以使用 html 标签,只能使用 rn 提供的原生组件,或第三方提供的可以用于 rn 的组件
原生组件列表请参看官方链接:https://reactnative.cn/docs/components-and-apis
主要有以下核心组件:
| 组件名 | 等效 html 标签 | 重要的特殊之处 |
|---|---|---|
| View | div | 无点击事件 |
| Text | span | 所有直接文本必须包裹在 <Text> 之中,包括实体字符 |
| Image | img | 必须指明高度和宽度 |
| ScrollView | - | ScrollView 不可以嵌套在另一个 ScrollView 中 |
| TextInput | input | - |
样式
有了结构,自然要有样式
内联的样式可以直接通过组件的 style 属性进行书写,每个属性使用驼峰写法
注意每个标签可以具有的 style 是不一样的,比如 color 属性,无法设置在 View 组件上(因为 View 不能直接包含文本),只能设置在 Text 组件上
也可以使用内部样式,写法如下
1 | import {StyleSheet} from 'react-native'; |
create 之后的 styles 实质上也还是一个对象,可以通过 styles.container 来使用样式,只不过通过 StyleSheet.create 来创建的话,会有自动代码补全
使用时,直接书写于组件的 style 属性中。注意,react 原本是写于 className 属性中,此处不同
1 | <View style={styles.container}> |
也可以使用 spread 运算符
1 | <View style={{...styles.container, backgroundColor: 'black'}}> |
在上一章中我们引入了 less 支持,所以当然也可以写外部样式
1 | // index.less |
1 | import styles from './index.less' |
之后用法与内部样式一样
基本布局
为了达到类似 caho 的移动端效果,我们需要页脚
则有如下组件
1 | import {SafeAreaView, ScrollView, View} from 'react-native'; |
首先使用 SafeAreaView 作为外层,以做到 ios 支持。详见 https://reactnative.cn/docs/safeareaview
然后使用 ScrollView 包裹主要视图,使得主视图组件可以上下滑动;同时,提供一个自定义的 Footer 组件作为页脚
注意,此处页脚必须写在 ScrollView 外部,才可以固定在视图下部,起到类似于 positon: fixed; 之效果
为什么要这样?因为 rn 的 style 不支持 position: fixed;
如果写在 ScrollView 内部,就会造成必须滚动到页面最下方才可以看到页脚
同时,因为页脚现在类似 fixed,所以会遮挡掉 ScrollView 最末尾的部分,所以需要在 ScrollView 中放置一个等高的空组件来占位
路由
路由如何配置,是非常重要的一环,必须要了解
设计
参考 Caho,我暂且设置了如下路由
1 | interface Route { |
配置
使用 react-navigation 来实现路由
文档地址:https://reactnavigation.org/docs/getting-started/
安装依赖
1 | yarn add @react-navigation/native @react-navigation/native-stack react-native-screens react-native-safe-area-context |
然后打开 App.tsx,引入需要的组件
1 | import {NavigationContainer} from '@react-navigation/native'; |
react-navigation 要求我们通过 NavigationContainer 和 Stack 注册路由,之后才可以正常使用
注册写法如下
1 | import router from './router'; |
首先使用 <NavigationContainer> 创建 navigation 容器,然后使用 <Stack.Navigator> 创建路由栈,用于在不同路由之间往返,最后通过 <Stack.Screen> 声明每一个路由
对于每条路由,可以手写,也可以如上这般通过数组遍历来完成,但要注意,<Stack.Navigator> 只接受 <Stack.Screen> 作为直接子级
对于每个 Screen,必要参数有 name 和 component,用于指示其唯一标识符和要渲染的组件。上例中的 key 是因为数组方法 map 要求对每个组件传入 key 作为唯一标识符
此处的 component 使用了一个包装函数,来使得所有组件共用相同的布局,不需要各自引入页脚
此外,还可以传入 options 来指示路由的标题等内容。上例中传入了 title 作为标题,headerTitleAlign 作为标题的对齐方式,headerRight 作为附加在标题右侧的组件。该标题会渲染在每个页面的最上方,等效顶边栏
现在就完成路由的配置了,启动应用就会发现应用路由到了 initialRouteName 所指示的组件
如果没有指示 initialRouteName,则会路由到 <Stack.Screen> 列表中的第一个组件
跳转
可是这样只能到达一个页面呀,该怎么前往其它页面呢
可以使用注入的 navigation
对于通过路由到达的每个组件,其 props 中均会被注入一个 navigation 导航器,该导航器具有两个重要方法:
navigate: (navigationName: NavigationName, payload?: any) => void;,第一个参数是路由名 (name),第二个参数可选,是通过路由传递的参数getState: () => any;,可以获得上层路由传递过来的参数,包含路由栈内全部的参数
显然,这是归属于路由的功能,但是 react-navigation 不提供 navigation 的类型定义,所以我们可以在 ./src/router/index.ts 中提供我们自己的类型定义
1 | const paths = [ |
通过这样的定义,我们就可以在外部使用 navigation 的使用,声明其类型为 Navigation,并在其 navigate 方法中使用代码自动补全
然后,我们可以在任意的直接路由到达的组件中,获取 navigation 导航器,例如
1 | // ./src/screen/user/index.tsx |
则从页脚跳转到 /user/[id] 的代码如下
1 | navigation.navigate('/user/[id]', {id: userId}) |
页脚
刚才一直说页脚,它是怎么实现的呢?
其实就是在 View 里面放 Icon,2333
1 | import React from 'react'; |
注意,此处使用了 onPress 属性,可以认为等效于在写 html 时的 onClick 属性,但是 View 上是没有该属性的,需要使用 TouchableOpacity 等可点击组件,但这是后面的内容了
感谢阅读