react native 外的 第三方组件
(一)与rn核心组件的使用步骤区别:
- 需单独安装
- 配置
- 使用
(二)第三方组件概览
1 WebView
- 描述: WebView 相当于一个内置浏览器,它允许你在应用内部显示网页,从而集成外部网站或在线资源。
2 Picker
- 描述: Picker 是一个下拉选择框组件,用于在应用中提供一个简洁的界面,让用户可以从一组选项中选择一个。
3 Swiper
- 描述: Swiper 组件用于展示轮播效果,非常适用于引导页面或展示图片集,支持手势滑动和自动播放功能。
4 AsyncStorage
- 描述: AsyncStorage 是一个简单的、异步的、持久化的键值对存储系统,用于在本地保存少量数据,适合存储用户偏好或应用状态。
5 Geolocation
- 描述: Geolocation 组件用于获取设备的当前位置信息。它可以提供精确的地理坐标,支持实时位置跟踪。
6 Camera
- 描述: Camera 组件允许应用调用设备的摄像头拍照或录像。它可以用于添加图像上传或现场视频捕捉的功能。
以上每个组件都在现代应用开发中扮演着重要的角色,提供了丰富的功能和用户体验。
(三)详细学习
1 WebView
CocoaPods
CocoaPods 是一个用于管理 iOS 和 macOS 应用开发中 Objective-C 和 Swift 语言项目的依赖项管理工具。它支持自动化地处理外部库的集成问题,帮助开发者更高效地管理项目中使用的各种第三方库和框架。
主要特点:
自动化依赖管理:CocoaPods 可以自动解析项目所需的第三方库依赖关系,并确保所有依赖项都兼容并且最新。
简化安装过程:通过编写一个名为 Podfile 的配置文件,你可以声明项目需要哪些第三方库。执行 pod install 命令后,CocoaPods 会自动下载并集成这些库。
版本控制:CocoaPods 允许你指定依赖库的版本,帮助避免因库更新带来的潜在问题,同时也可以轻松更新到新版本。
开放和共享:它利用一个名为 Specs 的中央仓库来管理各种公共的依赖库描述文件,任何人都可以向其贡献自己的库。
使用场景:
开发者在创建和维护 iOS 或 macOS 应用时,往往需要使用第三方库来增加新功能或者减少重复的工作
1 URL
// ESLint 规则禁用说明:关闭了关于 React Native 中内联样式的 ESLint 警告。
/* eslint-disable react-native/no-inline-styles */
// React 组件和基础组件导入被注释掉,因为它们在这段代码中未使用。
// 如果你需要使用 Text, StyleSheet, View 等组件,可以取消注释。
// import {Text, StyleSheet, View} from 'react-native';
// 导入 React 默认库,以及 React 组件基类。
import React, {Component} from 'react';
// 从 react-native-webview 包导入 WebView 组件。
// WebView 组件用于在你的应用中显示一个全功能的浏览器。
import {WebView} from 'react-native-webview';
// 定义 Index 类,这个类继承自 Component,使其成为一个 React 组件。
class MyWeb extends Component {
// render 方法是每个 React 组件必须实现的方法,它定义了组件的 UI。
render() {
// 返回 WebView 组件,用于加载并显示给定的 uri。
// uri 设为 'https://m.baidu.com',WebView 将会加载并显示这个网址的内容。
return (
// WebView 组件的样式被设置为 marginTop: 20,这意味着它会在顶部留出 20 像素的空间。
// 这个内联样式只是为了快速示例,通常推荐使用 StyleSheet.create 来创建样式。
<WebView source={{uri: 'https://m.baidu.com'}} style={{marginTop: 20}} />
);
}
}
// 将 Index 组件导出为模块的默认导出。
// 这使得其他文件可以通过 import Index from '<path>' 的形式导入 Index 组件。
export default MyWeb
2 html
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
// 定义 Index 类,这个类继承自 Component,使其成为一个 React 组件。
class MyWeb extends Component {
// render 方法是每个 React 组件必须实现的方法,它定义了组件的 UI。
render() {
// 返回 WebView 组件,用于加载并显示给定的 uri。
return (
<WebView
source={{
html: "<h1 >erewfg<h1/>"
}}
style={{ marginTop: 120 }} />
);
}
}
// 将 Index 组件导出为模块的默认导出。
// 这使得其他文件可以通过 import Index from '<path>' 的形式导入 Index 组件。
export default MyWeb
import React from 'react';
import { WebView } from 'react-native-webview';
const YourComponent = () => {
const htmlContent = `
<h1>21345678<h1/>
`;
return (
<WebView
originWhitelist={['*']}
source={{ html: htmlContent }}
style={{ marginTop: 100 }} // 顶部留出 100 像素的空间。
/>
);
};
export default YourComponent;
2 Picker
/*prettier/prettier */
/* eslint-disable react-native/no-inline-styles */
import {View, StyleSheet} from 'react-native';
import React, {Component} from 'react';
import {Picker} from '@react-native-picker/picker';
export default class Index extends Component {
constructor() {
super();
this.state = {
color: 'white',
};
}
render() {
return (
<View style={[styles.container, {backgroundColor: this.state.color}]}>
<Picker
mode="dropdown" // 只在安卓下有效
selectionColor="red"
selectedValue={this.state.color}
style={{height: 50, width: 160, fontSize: 15}}
onValueChange={(itemValue, itemIndex) => {
this.setState({color: itemValue});
}}>
<Picker.Item label="白色" value="white" />
<Picker.Item label="红色" value="red" />
</Picker>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
3 swiper
安装
在 React Native 中使用 Swiper 组件时,通常是通过第三方库,如 react-native-swiper,来实现轮播图或滑动视图功能。这个组件提供了多种属性来定制其行为和外观。以下是一些 react-native-swiper 的常用属性:
loop: 布尔值,决定轮播是否循环。设置为 true 时,轮播会无限循环。
autoplay: 布尔值,控制是否自动播放轮播图。当设置为 true 时,轮播图会自动滚动。
showsPagination: 布尔值,用于控制是否显示分页指示器。默认为 true。
index: 初始加载组件时显示的滑动块的索引,从0开始。
horizontal: 布尔值,设置滑动方向。默认为 true,表示水平方向滑动。设置为 false 则变为垂直滑动。
onIndexChanged: 函数,当轮播图切换时调用。提供当前索引作为参数。
loadMinimal: 布尔值,当设置为 true 时,仅加载当前项和缓冲项,以节省内存和减少加载时间。
paginationStyle: 对象,自定义分页指示器的样式。
activeDotColor: 字符串,定义活动点的颜色(当前视图的分页点)。
dotColor: 字符串,定义非活动点的颜色。
import { StyleSheet, Image, Dimensions, ScrollView, View, Text } from 'react-native';
import React, { Component } from 'react';
import Swiper from 'react-native-swiper';
export default class index extends Component {
render() {
return (
<ScrollView style={{ flex: 1 }}>
<Swiper autoplay={true} showsButtons={true} style={styles.wrapper}>
<View style={styles.slide}>
<Image
style={styles.slideImage}
source={require('./images/1.jpg')}
/>
<Text> </Text>
<Text style={styles.slideText}
> 宝贝玩滑梯</Text>
</View>
<View style={styles.slide}>
<Image
style={styles.slideImage}
source={require('./images/2.jpg')}
/>
<Text> </Text>
<Text style={styles.slideText}
> 宝贝笑</Text>
</View>
<View style={styles.slide}>
<Image
style={styles.slideImage}
source={require('./images/3.jpg')}
/>
<Text> </Text>
<Text style={styles.slideText}
> 宝贝回家</Text>
</View>
</Swiper>
<Text> </Text>
<Text style={styles.slideText}>《 宝贝春游日记》</Text>
<Text
>
</Text>
<Text> 今天是春季的一个阳光明媚的日子,我们一家三口决定去郊外游玩,感受春天的气息。
</Text>
<Text> 清晨,天空湛蓝,阳光温暖,我和爸爸妈妈兴奋地出发了。
我们的目的地是市郊的一个大公园。到了公园,首先映入眼帘的是满园的绿色和点缀其中的五颜六色的花朵。我们在花丛中漫步,我尤其喜欢那些漂亮的郁金香和茂盛的樱花。花儿们在春风中轻轻摇曳,好像在对我们说“欢迎”。</Text>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
wrapper: {
height: 250, // 增加了整个Swiper的高度
},
slide: {
flex: 1,
justifyContent: 'center', // 确保内容垂直居中
alignItems: 'center', // 确保内容水平居中
},
slideImage: {
height: 200,
width: Dimensions.get('window').width,
resizeMode: 'cover', // 确保图片覆盖整个可用宽度
},
slideText: {
color: 'red', // 将文本颜色设置为白色
fontSize: 16, // 增加字体大小以提高可读性
padding: 5, // 添加一些内边距
}
});
4 AsyncStorage
在React Native中,AsyncStorage是一个简单、异步、持久的Key-Value存储系统。它用于在设备上保存数据,使得数据即使在应用重启后也依然可以使用。
异步存储是一种数据存储方法,其操作(如读取、写入或删除数据)不会立即完成,而是在未来某个时刻完成,这些操作不会阻塞程序的继续执行。这意味着程序可以继续运行其他任务,而不必等待存储操作的完成。这种方式特别适用于需要处理大量数据或者在后台进行数据操作的应用,因为它可以提高应用的响应速度和性能。
1 异步存储的特点:
- 非阻塞性:异步操作允许用户界面或程序继续响应其他任务,而不是等待数据存储操作完成。
- 基于回调或Promise:异步存储通常使用回调函数或Promise来处理操作完成后的结果,这样可以在数据操作完成后执行特定的代码。
- 适用于Web和移动应用:在Web开发中,异步存储可以通过浏览器的Web Storage API、IndexedDB等技术实现。在移动开发中,如在React Native中,可以使用AsyncStorage库来实现。
2 异步存储 使用场景举例:
- Web应用中的数据缓存:例如,一个网页可以异步地将用户的浏览记录存储到本地,不影响用户继续浏览其他页面。
- 移动应用中的用户偏好设置:移动应用可以异步地存储用户的设置选择,如主题色或布局偏好,而不干扰用户的正常交互。
异步存储的使用提高了应用的效率和用户体验,尤其是在处理大量数据或在后台执行复杂任务时。
因此,类似于数据库理解 ,在React Native中,AsyncStorage主要是增删改查功能。
3 AsyncStorage 详解
https://react-native-async-storage.github.io/async-storage/docs/install/ 安装配置指导及学习手册
1. setItem数据存储
setItem
: 异步保存键值对。当需要存储用户设置或待持久保存的数据时使用。- 用法:
AsyncStorage.setItem('key', 'value')
import AsyncStorage from '@react-native-async-storage/async-storage';
const storeData = async (value) => {
try {
await AsyncStorage.setItem('@storage_Key', value)
} catch (e) {
// 保存错误
}
}
setObjectValue = async (value) => {
try {
const jsonValue = JSON.stringify(value)
await AsyncStorage.setItem('key', jsonValue)
} catch(e) {
// save error
}
console.log('Done.')
}
2. getItem读取数据
getItem
: 异步读取存储的值。- 用法:
AsyncStorage.getItem('key')
getMyStringValue = async () => {
try {
return await AsyncStorage.getItem('@key')
} catch(e) {
// read error
}
console.log('Done.')
}
getMyObject = async () => {
try {
const jsonValue = await AsyncStorage.getItem('@key')
return jsonValue != null ? JSON.parse(jsonValue) : null
} catch(e) {
// read error
}
console.log('Done.')
}
3. removeItem删除数据
removeItem
: 异步删除存储的键值对。- 用法:
AsyncStorage.removeItem('key')
removeValue = async () => {
try {
await AsyncStorage.removeItem('@MyApp_key')
} catch(e) {
// remove error
}
console.log('Done.')
}
4. 更新数据
- 数据更新: 可通过重复使用
setItem
方法使用新值覆盖旧值。 - 用法:
AsyncStorage.setItem('key', 'new value')
5. 清空所有数据
clear
: 异步清除所有AsyncStorage中的数据。慎用,因为这将删除所有当前存储的数据。- 用法:
AsyncStorage.clear()
6. 获取所有键
getAllKeys
: 异步获取所有存储的键。- 用法:
AsyncStorage.getAllKeys()
7. 批量获取多个键值
multiGet
: 异步同时获取多个键对应的值。- 用法:
AsyncStorage.multiGet(['key1', 'key2'])
8. 批量存储多个键值
multiSet
: 异步同时设置多个键值对。- 用法:
AsyncStorage.multiSet([['key1', 'value1'], ['key2', 'value2']])
9. 批量删除多个键
multiRemove
: 异步同时删除多个键。- 用法:
AsyncStorage.multiRemove(['key1', 'key2'])
10 mergeItem 合并键值对
mergeItem
mergeItem(key, value) 接受一个键和一个新的 JSON 字符串化的值,然后将这个新值合并到已经存在的值中。如果原先的值和新值都是 JSON 对象,mergeItem 会深层次地合并这两个对象的字段。如果键不存在,它会像 setItem 一样工作。
下面这个例子展示了如何用 mergeItem 更新嵌套的 JSON 对象中的一部分,而不是替换整个对象。这对于开发中的设置或用户首选项管理非常有用,可以避免读取整个对象、手动更新它然后再保存回去的繁琐流程。
请注意,AsyncStorage 的使用建议限制在轻量级数据存储,对于复杂或大量数据的存储,可能需要考虑更高级的数据库解决方案。
import AsyncStorage from '@react-native-async-storage/async-storage';
// 假设你已经有了这样一个存储的对象
const storeData = async () => {
const initialUserSettings = JSON.stringify({
volume: 10,
theme: 'dark'
});
try {
await AsyncStorage.setItem('@UserSettings', initialUserSettings);
} catch (error) {
// 错误处理
}
};
// 现在,假设我们只想更新主题,而不影响音量设置
const updateUserSettings = async () => {
const updatedSettings = JSON.stringify({
theme: 'light'
});
try {
await AsyncStorage.mergeItem('@UserSettings', updatedSettings);
} catch (error) {
// 错误处理
}
};
// 读取数据以验证更新
const readUserSettings = async () => {
try {
const result = await AsyncStorage.getItem('@UserSettings');
const settings = result ? JSON.parse(result) : null;
if (settings) {
console.log(settings); // 应输出: { volume: 10, theme: 'light' }
}
} catch (error) {
// 错误处理
}
};
// 初始化数据
storeData().then(() => {
// 更新数据
updateUserSettings().then(() => {
// 读取更新后的数据
readUserSettings();
});
});
11 useAsyncStorage
useAsyncStorage返回一个对象,该对象公开了允许与存储值交互的所有方法。
import React, { useState, useEffect } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
export default function App() {
const [value, setValue] = useState('value');
const { getItem, setItem } = useAsyncStorage('@storage_key');
const readItemFromStorage = async () => {
const item = await getItem();
setValue(item);
};
const writeItemToStorage = async newValue => {
await setItem(newValue);
setValue(newValue);
};
useEffect(() => {
readItemFromStorage();
}, []);
return (
<View style={{ margin: 40 }}>
<Text>Current value: {value}</Text>
<TouchableOpacity
onPress={() =>
writeItemToStorage(
Math.random()
.toString(36)
.substr(2, 5)
)
}
>
<Text>Update value</Text>
</TouchableOpacity>
</View>
);
}
注意
AsyncStorage
操作通常返回一个Promise,因此可以使用async/await或.then来处理异步操作的结果。- 在React Native 0.59及以上版本,
AsyncStorage
已从核心组件中移除,推荐使用社区维护的@react-native-community/async-storage
。
综合示例一
import { Text, StyleSheet, View, Button } from 'react-native'
import React, { Component } from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage'
export default class index extends Component {
storeData = async (value) => {
try {
await AsyncStorage.setItem('mytest', value)
} catch (e) {
// 保存错误
}
}
getData = async () => {
try {
const value = await AsyncStorage.getItem('mytest')
//保持key都是 mytest
if (value !== null) {
alert(value)
}
} catch (e) {
// read error
}
console.log('Done.')
}
render() {
return (
<View styles={[styles.container]}>
<Text></Text>
<Text></Text>
{/* /在storeData中传入参数 */}
<Button title='存储' onPress={this.storeData('Hello wdm')} />
<Button title='获取' onPress={this.getData } />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})
封装 Async storage
四个模块
增
set(key,value)
删
delete(key)|clear()
改
update(key,value)
查
get(key)
Storage.js
import AsyncStorage from '@react-native-async-storage/async-storage'
//写一个具有增删改查功能的模块 并封装成一个类
class Storage {
/**
* 添加数据
* @param {string} key
* @param {mixed} value
* @returns {Promise}
*/
//写具体的set添加数据的方法 set
//set 里面有key value两个参数
static set(key, value) {
//具体的执行逻辑
return AsyncStorage.setItem(key, JSON.stringify(value))
// 注意 此处JSON 为大写
//在保存对象或数组到 AsyncStorage 而setItem时,由于 AsyncStorage 只支持字符串类型的存储,
//所以需要使用 JSON.stringify() 方法将数据对象value转换为字符串
}
/**
* 获取数据
* @param {string} key
* @returns {Promise}
*/
static get(key) {
//读取存储在 AsyncStorage 中的数据时,会得到一个 JSON 字符串
//需要使用 JSON.parse() 将其转换回 JavaScript 对象
//使用then 在获取的key后面写一个function 我们这里用then来取到具体的数据 value
//value后面是执行函数 来判断 和处理value为空的情况
return AsyncStorage.getItem(key).then(value => {
if (value && value != '') {
// 如果value 有数据且 不是空字符的情况下
const jsonValue = JSON.parse(value)
return jsonValue
}
}).catch(() => null)
// .then后面我们还可以写.catch 对异常进行操作
}
/**
* 更新数据
* @param {string} key
* @param {mixed} newValue
* @returns {Promise}
*/
static update(key, newValue) {
return AsyncStorage.getItem(key).then(oldValue => {
//通过 typeof 来判断 newValue 的类型
//三元表达式 是string 则不做任何处理 否则 判定为复杂结构的对象Object
//这时候 我们调用一下Object 中的assign方法 可以合并对象当中的同名属性
newValue = typeof newValue === 'string' ? newValue : Object.assign({}, oldValue, newValue)
return AsyncStorage.setItem(key, JSON.stringify(newValue))
})
}
/**
* 删除指定的 key
* @param {} key
* @returns
*/
static delete(key) {
return AsyncStorage.removeItem(key)
}
/**
* 清空所有数据
* @returns
*
*/
static clear() {
return AsyncStorage.clear()
}
}
// 将 Storage 导出
export default Storage
自己封装模块的使用
index.js
import { Text, StyleSheet, View, Button } from 'react-native'
import React, { Component } from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage'
import Storage from './storage'
export default class index extends Component {
storeData = async (value) => {
try {
await AsyncStorage.setItem('mytest', value)
} catch (e) {
// 保存错误
}
}
getData = async () => {
try {
const value = await AsyncStorage.getItem('mytest')
//保持key都是 mytest
if (value !== null) {
alert(value)
} else {
alert('value == null')
}
} catch (e) {
// read error
}
console.log('Done.')
}
addData = async (value) => {
try {
// await AsyncStorage.setItem('mytest01', value)
await Storage.set('mytest01', value)
} catch (e) {
// 保存错误
}
}
getMyData = async () => {
try {
const value = await AsyncStorage.getItem('mytest01')
//保持key都是 mytest
if (value !== null) {
alert(value)
} else {
alert('value == null001')
}
} catch (e) {
// read error
}
console.log('Done.')
}
render() {
return (
<View styles={[styles.container]}>
<Text></Text>
<Text></Text>
{/* /在storeData中传入参数 */}
{/* 实现方式是在 onPress 属性中直接调用函数并传递参数,这会导致在组件渲染时立即调用这些函数,而不是等到按钮被点击时调用。
*/}
<Button title='原生:存储' onPress={this.storeData('Hello wdm')} />
<Button title='原生:获取' onPress={this.getData} />
{/* // 直接掉用模块里面的清空方法 来测试是否导入模块成功 */}
<Button title='清空' onPress={Storage.clear} />
{/* onPress 事件处理器中使用 () => 来允许定义一个函数,而无需使用 function 关键字。
这使得代码更加简洁易读。
这里 () => 后面跟着的 {} 中是函数体,如果函数体只有一条语句,
甚至可以省略 {} 和 return 语句:
() => {
this.addData('Hello wdm001');
}
等同于 () => this.addData('Hello wdm001')
*/}
{/* 应该将 onPress 的值设置为一个函数,当按钮被点击时调用这个函数。
如果需要传递参数,可以使用箭头函数来封装调用。 */}
<Button title='自制:存储' onPress={() => { this.addData('Hello 001') }} />
<Button title='自制:获取' onPress={this.getMyData} />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})
4 geolocation获取定位
安装
npm install react-native-geolocation-service
或者
yarn add react-native-geolocation-service
适当配置了 Info.plist 文件来请求位置权限,添加描述依赖
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need access to your location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>We need access to your location</string>
报错尝试重新装依赖:
yarn install
cd ios
pod install
cd ..
运行前清除缓存
yarn start --reset-cache
运用:
import React, { Component } from 'react';
import { View, Text, Button, StyleSheet, Platform } from 'react-native';
import Geolocation from 'react-native-geolocation-service';
// 定义 GeoLocationExample 组件,它继承了 Component 类
export default class GeoLocationExample extends Component {
// 初始化组件状态
state = {
location: null, // 存储位置信息
loading: false, // 标记是否正在获取位置
error: null // 存储可能发生的错误信息
};
// 组件挂载后调用(组件被加载到屏幕上时)
componentDidMount() {
this.requestLocationPermission(); // 请求位置权限
}
// 请求位置权限的函数
requestLocationPermission = () => {
if (Platform.OS === 'ios') { // 检查操作系统是否是 iOS
// 请求位置权限
Geolocation.requestAuthorization('whenInUse').then(result => {
if (result === 'granted') { // 如果用户授予位置权限
this.getLocation(); // 获取位置信息
} else {
// 如果用户拒绝权限,更新错误状态
this.setState({ error: 'Location permission not granted' });
}
});
}
};
// 获取位置信息的函数
getLocation = () => {
this.setState({ loading: true, error: null }); // 开始加载,重置错误信息
Geolocation.getCurrentPosition(
(position) => {
// 成功获取位置信息后的回调函数
this.setState({ location: position, loading: false }); // 更新位置信息,停止加载
},
(error) => {
// 获取位置失败后的回调函数
this.setState({ loading: false, error: error.message }); // 停止加载,更新错误信息
},
// 高精度位置信息的选项
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
);
};
// 渲染组件的函数
render() {
const { location, loading, error } = this.state; // 从 state 中解构所需的数据
return (
<View style={styles.container}>
<Text>Location Info:</Text>
{loading && <Text>Loading...</Text>}
{/* // 如果正在加载,显示加载提示 */}
{error && <Text>Error: {error}</Text>}
{/* // 如果有错误,显示错误信息 */}
{location && (
<Text>
{/* // 如果位置信息存在,显示经纬度 */}
Latitude: {location.coords.latitude}, Longitude: {location.coords.longitude}
</Text>
)}
<Button title="Get Location" onPress={this.getLocation} />
{/* // 按钮用来触发获取位置的函数 */}
</View>
);
}
}
// StyleSheet 创建组件的样式
const styles = StyleSheet.create({
container: {
flex: 1, // 组件占满整个屏幕
justifyContent: 'center', // 子元素垂直居中
alignItems: 'center', // 子元素水平居中
padding: 20 // 内边距为 20
}
});