React Native 有一个内置的命令行界面,你可以用它来生成一个新项目。您可以使用 Node.js 附带的 访问它,而无需全局安装任何内容。让我们创建一个名为“AwesomeProject”的新 React Native 项目:npx
现在ReactNative的项目就创建完成了,我们就用VScode打开,运行项目以及编辑。
2、修改App.tsx文件
3、双击R键重新加载代码
4、Ctrl+M或摇晃手机打开调试模式
一、长度的单位
在开始任何布局之前,让我们来首先需要知道,在写React Native组件样式时,长度的不带单位的,它表示“与设备像素密度无关的逻辑像素点”。
这个怎么理解呢?
我们知道,屏幕上一个发光的最小点,对应着一个pixel(像素)点。
假设下面三个矩形,代表三个屏幕大小一样的设备,但是,它们拥有的分辨率(resolution)不同:
图1.相同尺寸的设备 不同的分辨率
图上的每一个小格子,其实就代表了一个像素(pixel)。可以看到,一个像素点的大小,在这个三个物理尺寸一样但拥有不同分辨率的设备上,是不一样的。
如果我们以像素为单位来设置一个界面元素的大小,比如说2px的高度,那么这2px的长度上面的设备中就会是下面这个样子:
图2.不同分辨率下的2px实际高度
它们真实显示出的长度是不一样的。
我们想要一种长度单位,在同样物理尺寸大小的屏幕上(不论分辨率谁高谁低,只要物理尺寸大小一样即可),1个单位的长度所代表的物理尺寸是一样的。这种单位就应该是独立于分辨率的,把它起一个名字叫做 density-independent pixels,简称dp。这其实就是Android系统中所使用的长度单位。
举例来说,2dp宽,2dp高的内容,在不同分辨率但屏幕尺寸一样的设备上所显示出的物理大小是一样的。(一个题外话:有些Android开发者建议所有可点击的按钮,宽高都不应该少于48dp。)
图3. 2dp * 2dp大小的内容 在同样尺寸的屏幕中所占据的物理大小一致
Android中字体大小使用另外一个单位,叫做scale independent pixels,简称sp。这个单位和dp很类似,不过它通常是用在对字体大小的设置中。通过它设置的字体,可以根据系统字体大小的变化而变化。
pixel与dp存在一个公式:px = dp * (dpi/160)。
dpi表示dot per inch,是每英寸上的像素点,它也有个自己的计算公式,具体这里就不展开了。只需要知道我们之所以要使用一个独立于设备分辨率的单位,主要是为了让应用在不同分辨率的设备中,看起来一致。
在RN中,同样也拥有一个类似于dp的长度单位。如果我们想知道自己的屏幕以这种长度的计量下是多少单位,可以通过引入react-native包中的Dimensions拿到,同时还可以查看本机的像素比例是多少。
显示如下:
图4. 当前手机的屏幕信息
它反映出,当前手机屏幕的宽度占据360个单位,高度占据640个单位。像素比例是3,实际上这就是一个 1080 * 1920 像素的手机。其中1080 = width * pixelRadio, 1920 = height * pixelRatio
在 React Native 中,仍然是使用 JavaScript 来写样式,所有的核心组件都接受名为 style 的属性,这些样式名基本上都遵循 web 上的 CSS 属性名
1、通过 style 属性直接声明
2、在 style 属性中调用 StyleSheet 声明的样式
引入:import {StyleSheet, View} from 'react-native'
声明:const styles = StyleSheet.create({foo: {样式1}, bar: {样式2}})
使用:<View style={[styles.foo, styles.bar]}>内容</View>
1、没有继承性
RN 中的继承只发生在 Text 组件上
2、样式名采用小驼峰命名
fontSize VS font-size
3、所有尺寸都没有单位
width: 100
4、有一些特殊的样式名
marginHorizontal(水平外边距), marginVertical (垂直外边距)
在 RN 中使用 flexbox 规则来指定某个组件的子元素的布局,flexbox 可以在不同屏幕尺寸上提供一致的布局结构
flexbox 术语
容器(container)
采用 flex 布局的元素,称为 flex 容器,简称 容器
项目(item)
容器所有的子元素,称为 flex 项目,简称 项目
主轴(main axis)
交叉轴(cross axis)
flex 属性决定元素在主轴上如何 填满 可用区域。整个区域会根据每个元素设置的 flex 属性值被分割成多个部分
在下面的例子中,在设置了宽高为100%的容器中,有红色、黄色和绿色三个子 View,红色设置了 flex:1,黄色设置了 flex:2,绿色设置了 flex:3,这意味着 红色 view 占据整个容器的 1/6,黄色 view 占据整个容器的 2/6,绿色 view 占据整个容器的 3/6
谈到布局我们从原生讲起,在iOS的世界里我们是有X轴、Y轴的,
那么在React Native的世界里对应的就是flexDirection属性,
它是有row(行,我们可以和X轴对应,水平方向)、column(列,我们可以和Y轴对应,垂直方向),
flexDirection决定了子控件的排列方向,也就决定了主次轴,
如果是row那么X轴就是主轴,Y轴就是次轴(侧轴),如果是column那么Y轴就是主轴,X轴就是次轴(侧轴)。
我们的justifyContent和alignItems就是参照于主次轴的,justifyContent参照主轴,alignItems参照次轴。
换言之justifyContent和alignItems依赖于flexDirection,离开了flexDirection,两者也就没有了意义。
声明主轴的方向,子元素是应该沿着 水平轴(row)方向排列,还是沿着 竖直轴(column)方向排列
在 Web 里默认是 水平轴(row),在 RN 里默认是 垂直轴(column)
在组件的 style 中指定 justifyContent 可以决定其子元素沿着 主轴 的排列方式
取值:
flex-start: 默认值,左对齐
flex-end: 右对齐
center: 居中
space-between: 两端对齐,项目之间的间隔都相等
space-around: 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与两端的间隔大一倍
space-evenly:每个项目之间的间隔相等,均匀排列每个项目
在组件的 style 中指定 alignItems 可以决定其子元素沿着 交叉轴 的排列方式
我们经常使用alignItems来调整子控件,这个值主要是控制次轴的
取值:
stretch: 默认值,根据容器交叉轴的高度撑满容器子元素
注意:要使 stretch 选项生效的话,子元素在 交叉轴 方向上不能有固定的尺寸
flex-end: 右对齐
center: 居中
space-between: 两端对齐,项目之间的间隔都相等
space-around: 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与两端的间隔大一倍
space-evenly:每个项目之间的间隔相等,均匀排列每个项目
alignSelf 和 alignItems 具有相同的取值属性和作用,区别是:
alignItems 作用于容器下所有的子元素
alignSelf 作用于单个子元素,并且会覆盖 alignItems 指定的属性
flexWrap 属性作用于容器上,控制子元素溢出时如何在主轴上排列。默认是强制不换行
一个元素的position类型决定了其在父元素中的位置
position 取值:
relative:(默认值),元素的位置取决于文档流
absolute:元素会脱离正常的文档流
组件的宽度和高度决定了其在屏幕上显示的尺寸
1、指定宽高
RN 中的尺寸都是 无单位的,表示的是与设备像素密度无关的逻辑像素点
指定宽高一般用于在不同尺寸的屏幕上都显示成一样的大小
2、弹性(Flex)宽高
在组件中使用 flex 可以使其在可利用的空间中动态地扩张或收缩,一般会使用 flex:1 来指定某个组件扩张以撑满所有剩余的空间
如果有多个并列的子组件使用了 flex:1,则这些子组件会平分父容器的剩余的空间
如果这些并列的子组件的 flex 值不一样,则谁的值更大,谁占据剩余空间的比例就更大
注意:使用 flex 指定宽高的前提是其父容器的尺寸不为零
3、百分比宽高
用法和注意事项同 flex 宽高
4、设备宽高
用法:
获取设备宽度:Dimensions.get('window').width
获取设备高度:Dimensions.get('window).height
RN中的核心组件,是对原生组件的封装
原生组件
在 Android 开发中是使用 Kotlin 或 Java 来编写视图;在 iOS 开发中是使用 Swift 或 Objective-C 来编写视图。在 React Native 中,则使用 React 组件通过 JavaScript 来调用这些视图。在运行时,React Native 为这些组件创建相应的 Android 和 iOS 视图。由于 React Native 组件就是对原生视图的封装,因此使用 React Native 编写的应用外观、感觉和性能与其他任何原生应用一样。我们将这些平台支持的组件称为原生组件。
核心组件
中文网组件介绍:https://www.reactnative.cn/docs/components-and-apis
官网的核心主键,React Native 具有许多核心组件,从表单控件到活动指示器,应有尽有。你可以在API 章节找到它们。您将主要使用以下核心组件:
这是参考的核心组件有:
官网的案例:
效果:
Button是一个简单的跨平台的按钮组件。下面是一个最简示例:
AlertAndButton.tsx
上面这段代码会在 iOS 上渲染一个蓝色的标签状按钮,在 Android 上则会渲染一个蓝色圆角矩形带白字的按钮。点击这个按钮会调用"onPress"函数,具体作用就是显示一个 alert 弹出框。你还可以指定"color"属性来修改按钮的颜色。
运行效果:点击按钮弹出提示框
再试试下面这个使用Button
的例子吧。你可以点击"Tap to Play"来预览真实效果
buttonBasics.tsx
运行效果:
1、引入 import { View, Switch, StyleSheet } from "react-native";
2、使用 <Switch trackColor={{ false: "#767577", true: "#81b0ff" }} thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"} ios_backgroundColor="#3e3e3e" onValueChange={toggleSwitch} value={isEnabled} /> 3、参数 trackColor={false: color, true: color} 开启/关闭状态时的背景颜色。 ios_backgroundColor='x' 在iOS上,自定义背景颜色。当开关值为false或开关被禁用时(开关是半透明的),可以看到这个背景颜色。 onValueChange 当值改变的时候调用此回调函数,参数为新的值。 testID 用来在端到端测试中定位此视图。 thumbColor='x' 开关上圆形按钮的背景颜色。在 iOS 上设置此颜色会丢失按钮的投影。 tintColor='x' 关闭状态时的边框颜色(iOS)或背景颜色(Android)。 value=布尔值变量 表示此开关是否打开。默认为 false(关闭状态)。
运行效果:
ActivityIndicator的效果类似我们平时看到了loading,在android中ActivityIndicator是progressBar 的Indeterminate(false)模式,说白了就是一个半圆转啊转。
具体属性: 1、ViewPropTypes props… :包含View控件的所有属性,具体咱们看View的属性解释。 2、animating:是否显示,默认true(显示) 3、color: 指示器的颜色, ios默认为gray(#999999),android 默认使用progressBar的系统样式,取决于你设置的style。 4、size: 表示大小,可以设置的值有: ‘small’: 宽高各20 ‘large’: 宽高各36 5、hidesWhenStopped:此属性只在ios生效,当停止动画的时候,是否隐藏。默认为true。
运行效果:
1、source图片路径
运行效果:
使用Image组件时,如果默认不对resizeMode进行设置,那么 图片会按照宽高比例中较小的一方显示,长的一方将被裁切掉两端
Image的resizeMode属性:
resizeMode enum(‘cover’,‘contain’,‘stretch’,‘repeat’,‘center’)
如果我们需要将原图完全显示出来可以设置
resizeMode =’contain’:
图片将按比例缩放按宽和高较长的显示,短的方向两边留出空白
resizeMode =’stretch’:
图片将完全显示出来并拉伸变形铺满整个屏幕
但如果你的尺寸比例不合适,可能会出现下列尴尬画面
repeat:图片重复并铺满屏幕(不支持android)
center:图片不拉伸不缩放且居中
最后提醒一下大家,ImageBackground组件中的resizeMode是无效的
运行效果:
运行效果:
ScrollView是一个通用的可滚动的容器,你可以在其中放入多个组件和视图,而且这些组件并不需要是同类型的。ScrollView不仅可以垂直滚动(默认),还能水平滚动(通过horizontal属性来设置)。
ScrollView常用属性:
horizontal(布尔值):当此属性为true的时候,所有的的子视图会在水平方向上排成一行,而不是默认的在垂直方向上排成一列。默认值为false。
showsHorizontalScrollIndicator(布尔值):当此属性为true的时候,显示一个水平方向的滚动条。
showsVerticalScrollIndicator(布尔值):与showsHorizontalScrollIndicator相对,当此属性为true的时候,显示一个垂直方向的滚动条。
OnMomentumScrollEnd(function) :当一帧滚动完毕的时候调用,e.nativeEvent.contentOffset,可以用来获取偏移量。
onScrollBeginDrag(function) :当开始手动拖拽的时候调用。
onScrollEndDrag(function) :当结束手动拖拽的时候调用。
onScroll(function) :在滚动的过程中,每帧最多调用一次此回调函数。调用的频率可以用scrollEventThrottle属性来控制。
运行效果:有滚动效果
用于呈现分区列表的高性能界面,支持最方便的功能:
如果您不需要部分支持并且想要更简单的界面,请使用<FlatList>
官网案例:
运行效果:
Animated
库旨在使动画变得流畅,强大并易于构建和维护。Animated
侧重于输入和输出之间的声明性关系,以及两者之间的可配置变换,此外还提供了简单的 start/stop
方法来控制基于时间的动画执行。
创建动画最基本的工作流程是先创建一个 Animated.Value
,将它连接到动画组件的一个或多个样式属性,然后使用Animated.timing()
通过动画效果展示数据的变化:
Animated
库旨在使动画变得流畅,强大并易于构建和维护。Animated
侧重于输入和输出之间的声明性关系,以及两者之间的可配置变换,此外还提供了简单的 start/stop
方法来控制基于时间的动画执行。
创建动画最基本的工作流程是先创建一个 Animated.Value
,将它连接到动画组件的一个或多个样式属性,然后使用Animated.timing()
通过动画效果展示数据的变化:
运行效果:点击FADEIN 有淡出效果,FADEOUT淡出效果
通过命令安装第三的组件
比如如图所示:
引入的命令:
配置:
示例:MyWeb.js
运行效果:
引入的命令:
配置:
示例:PickerDemo.js
运行效果:
引入的命令:
配置:
示例:SwiperDemo.js
运行效果:
问题
最近在使用react native开发app的发现一个问题:
报错详情:
可以看到,这是jsx的正确写法,并没有语法错误,但是eslint还是报错,大致意思就是意外的符号<,可以大概推断是eslint没有正确解析jsx语法造成的,虽然程序可以正常运行,但是对于强迫症来说,确实受不了。
分析
原因:开发环境与ESLint当前的解析功能不兼容
解决方案:使用babel-eslint解析
解决
安装babel-eslint
在.eslintrc.js中加入
问题解决,报错清除。
1、完成如下页面布局