ReactNative for Harmony 项目鸿蒙化三方库集成实战:react-native-webview
是 React Native 社区最流行的 WebView 组件,提供了一套完整的网页加载和交互解决方案。它支持加载网络 URL、本地 HTML 文件、注入 JavaScript、处理网页事件等多种功能,并且完全兼容 Android、iOS 和 HarmonyOS 三端。库名称版本信息13.10.5: 支持 RN 0.72 版本13.15.1: 支持 RN 0.77 版本官方仓库主要功能加载网络

📋 前言
react-native-webview 是 React Native 社区最流行的 WebView 组件,提供了一套完整的网页加载和交互解决方案。它支持加载网络 URL、本地 HTML 文件、注入 JavaScript、处理网页事件等多种功能,并且完全兼容 Android、iOS 和 HarmonyOS 三端。
🎯 库简介
基本信息
- 库名称: @react-native-ohos/react-native-webview
- 版本信息:
13.10.5: 支持 RN 0.72 版本13.15.1: 支持 RN 0.77 版本
- 官方仓库: https://github.com/react-native-oh-library/react-native-webview
- 主要功能:
- 加载网络 URL 和本地 HTML
- 注入 JavaScript 代码
- 处理网页加载事件
- 网页与原生通信
- 支持多种配置选项
- 兼容 Android、iOS 和 HarmonyOS
- 兼容性验证:
- 鸿蒙化版本 13.10.4-rc.4 及之后需要 DevEco Studio 6.0.0 (API20) 及以上版本
为什么需要这个库?
- 功能完整: 提供完整的 WebView 功能
- 跨平台: 在三端提供一致的体验
- 易于使用: API 简单直观
- 性能优异: 原生实现,高效稳定
- 灵活配置: 支持多种配置选项
📦 安装步骤
1. 使用 npm 安装
根据您的 RN 版本选择对应的包名:
npm install @react-native-ohos/react-native-webview@13.10.5-rc.1
2. 验证安装
安装完成后,检查 package.json 文件,应该能看到新增的依赖:
{
"dependencies": {
"@react-native-ohos/react-native-webview": "^13.10.5-rc.1",
// ... 其他依赖
}
}
🔧 HarmonyOS 平台配置 ⭐
1. 在工程根目录的 oh-package.json5 添加 overrides 字段
首先需要使用 DevEco Studio 打开项目里的 HarmonyOS 工程 harmony
打开 harmony/oh-package.json5,添加以下配置:
{
...
"overrides": {
"@rnoh/react-native-openharmony": "^0.72.90"
}
}
2. 引入原生端代码
方法一:通过 har 包引入(不推荐)
[!TIP] har 包位于三方库安装路径的
harmony文件夹下。
打开 entry/oh-package.json5,添加以下依赖:
"dependencies": {
"@rnoh/react-native-openharmony": "0.72.90",
"@react-native-ohos/react-native-webview": "file:../../node_modules/@react-native-ohos/react-native-webview/harmony/rn_webview.har"
}
点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install
方法二:直接链接源码
步骤 1: 把 <RN工程>/node_modules/@react-native-ohos/react-native-webview/harmony 目录下的源码 rn_webview 复制到 harmony(鸿蒙壳工程)工程根目录下。
步骤 2: 在 harmony 工程根目录的 build-profile.template.json5(若存在)和 build-profile.json5 添加以下模块:
modules: [
...
{
name: 'rn_webview',
srcPath: './rn_webview',
}
]
步骤 3: 打开 rn_webview/oh-package.json5,修改 react-native-openharmony 和项目的版本一致。
步骤 4: 打开 entry/oh-package.json5,添加以下依赖:
"dependencies": {
"@rnoh/react-native-openharmony": "0.72.90",
"@react-native-ohos/react-native-webview": "file:../rn_webview"
}
步骤 5: 点击 DevEco Studio 右上角的 sync 按钮
3. 配置 CMakeLists 和引入 WebViewPackage
打开 entry/src/main/cpp/CMakeLists.txt,添加:
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp")
set(CMAKE_ASM_FLAGS "-Wno-error:unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,noexecstack -s -fPIE -pie")
add_compile_definitions(WITH_HITRACE_SYSTRACE)
set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
add_library(rnoh_app SHARED
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp" "./PackageProvider.cpp")
target_link_libraries(rnoh_app PUBLIC rnoh)
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-webview/src/main/cpp" ./webview)
+ target_link_libraries(rnoh_app PUBLIC rnoh_webview)
打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "SamplePackage.h"
+ #include "WebViewPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
std::make_shared<SamplePackage>(ctx),
+ std::make_shared<WebViewPackage>(ctx)
};
}
4. 在 ArkTs 侧引入 WebView 组件
找到 function buildCustomComponent(),一般位于 entry/src/main/ets/pages/index.ets 或 entry/src/main/ets/rn/LoadBundle.ets,添加:
+ import { WebView, WEB_VIEW } from "@react-native-ohos/react-native-webview"
@Builder
function buildCustomComponent(ctx: ComponentBuilderContext) {
+ if (ctx.componentName === WEB_VIEW) {
+ WebView({
+ ctx: ctx.rnComponentContext,
+ tag: ctx.tag
+ })
+ }
...
}
[!TIP] 本库使用了混合方案,需要添加组件名。
在 entry/src/main/ets/pages/index.ets 或 entry/src/main/ets/rn/LoadBundle.ets 找到常量 arkTsComponentNames 在其数组里添加组件名:
const arkTsComponentNames: Array<string> = [
+ WEB_VIEW
];
5. 在 ArkTs 侧引入 WebViewPackage
打开 entry/src/main/ets/RNPackagesFactory.ts,添加:
+ import { WebViewPackage } from '@react-native-ohos/react-native-webview/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new SamplePackage(ctx),
+ new WebViewPackage(ctx)
];
}
6. 运行
点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install
然后编译、运行即可。
💻 完整代码示例
下面是一个完整的示例,展示了 react-native-webview 的各种使用场景:
import React, { useRef, useState } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
TextInput,
ScrollView,
SafeAreaView,
ActivityIndicator,
} from 'react-native';
import { WebView, WebViewNavigation } from 'react-native-webview';
function WebViewDemo() {
const webViewRef = useRef<WebView>(null);
const [url, setUrl] = useState('https://reactnative.dev/');
const [canGoBack, setCanGoBack] = useState(false);
const [canGoForward, setCanGoForward] = useState(false);
const [loading, setLoading] = useState(false);
const [currentUrl, setCurrentUrl] = useState('');
const [error, setError] = useState<string | null>(null);
const [progress, setProgress] = useState(0);
const handleGoBack = () => {
if (webViewRef.current && typeof webViewRef.current.goBack === 'function') {
webViewRef.current.goBack();
}
};
const handleGoForward = () => {
if (webViewRef.current && typeof webViewRef.current.goForward === 'function') {
webViewRef.current.goForward();
}
};
const handleReload = () => {
webViewRef.current?.reload();
};
const handleLoad = () => {
webViewRef.current?.injectJavaScript(`
(function() {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'pageInfo',
title: document.title,
url: window.location.href
}));
})();
true;
`);
};
const handleMessage = (event: any) => {
try {
const data = JSON.parse(event.nativeEvent.data);
console.log('收到网页消息:', data);
} catch (e) {
console.log('收到网页消息:', event.nativeEvent.data);
}
};
const loadUrl = () => {
if (url.trim()) {
setError(null);
}
};
const useDefaultUrl = () => {
setUrl('https://reactnative.dev/');
setError(null);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
{/* 顶部工具栏 */}
<View style={styles.toolbar}>
<TouchableOpacity
style={[styles.navButton, !canGoBack && styles.disabledButton]}
onPress={handleGoBack}
disabled={!canGoBack}
>
<Text style={styles.navButtonText}>←</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.navButton, !canGoForward && styles.disabledButton]}
onPress={handleGoForward}
disabled={!canGoForward}
>
<Text style={styles.navButtonText}>→</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.navButton}
onPress={handleReload}
>
<Text style={styles.navButtonText}>↻</Text>
</TouchableOpacity>
<TextInput
style={styles.urlInput}
value={url}
onChangeText={setUrl}
onSubmitEditing={loadUrl}
placeholder="输入网址"
autoCapitalize="none"
autoCorrect={false}
/>
<TouchableOpacity
style={styles.goButton}
onPress={loadUrl}
>
<Text style={styles.goButtonText}>前往</Text>
</TouchableOpacity>
</View>
{/* 进度条 */}
{loading && progress > 0 && progress < 1 && (
<View style={styles.progressBarContainer}>
<View style={[styles.progressBar, { width: `${progress * 100}%` }]} />
</View>
)}
{/* 错误提示 */}
{error && (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>{error}</Text>
</View>
)}
{/* WebView */}
<View style={styles.webviewContainer}>
{loading && (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#42a5f5" />
<Text style={styles.loadingText}>加载中...</Text>
</View>
)}
<WebView
ref={webViewRef}
source={{ uri: url }}
style={styles.webview}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
scalesPageToFit={true}
showsHorizontalScrollIndicator={true}
showsVerticalScrollIndicator={true}
onNavigationStateChange={(navState: WebViewNavigation) => {
setCanGoBack(navState.canGoBack);
setCanGoForward(navState.canGoForward);
setCurrentUrl(navState.url);
}}
onLoadStart={() => {
setLoading(true);
setError(null);
}}
onLoadEnd={() => {
setLoading(false);
// 延迟执行 JavaScript 注入,确保 WebView 已完全加载
setTimeout(() => {
handleLoad();
}, 100);
}}
onLoadProgress={({ nativeEvent }) => {
setProgress(nativeEvent.progress);
}}
onHttpError={(syntheticEvent) => {
const { nativeEvent } = syntheticEvent;
setError(`HTTP 错误: ${nativeEvent.statusCode}`);
setLoading(false);
}}
onError={(syntheticEvent) => {
const { nativeEvent } = syntheticEvent;
setError(`加载错误: ${nativeEvent.description}`);
setLoading(false);
}}
onMessage={handleMessage}
injectedJavaScriptBeforeContentLoaded={`
window.addEventListener('load', function() {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'loaded',
timestamp: new Date().toISOString()
}));
});
`}
ignoreSilentHardwareSwitch={true}
/>
</View>
{/* 当前 URL 显示 */}
{currentUrl && (
<View style={styles.urlDisplay}>
<Text style={styles.urlLabel}>当前页面:</Text>
<Text style={styles.urlText} numberOfLines={1}>
{currentUrl}
</Text>
</View>
)}
{/* 功能按钮 */}
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.actionButton}
onPress={useDefaultUrl}
>
<Text style={styles.actionButtonText}>React Native 官网</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.actionButton}
onPress={() => {
webViewRef.current?.injectJavaScript(`
alert('这是一个来自 React Native 的注入消息!');
true;
`);
}}
>
<Text style={styles.actionButtonText}>注入 JS</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.actionButton}
onPress={() => {
if (webViewRef.current && typeof webViewRef.current.clearCache === 'function') {
webViewRef.current.clearCache(true);
}
}}
>
<Text style={styles.actionButtonText}>清除缓存</Text>
</TouchableOpacity>
</View>
{/* 说明 */}
<View style={styles.infoSection}>
<Text style={styles.infoTitle}>功能说明:</Text>
<Text style={styles.infoText}>
• 支持加载网络 URL 和本地 HTML 文件
</Text>
<Text style={styles.infoText}>
• 支持注入 JavaScript 代码
</Text>
<Text style={styles.infoText}>
• 支持网页与原生通信
</Text>
<Text style={styles.infoText}>
• 支持前进、后退、刷新等导航功能
</Text>
<Text style={styles.infoText}>
• 支持加载进度显示
</Text>
<Text style={styles.infoText}>
• 支持错误处理
</Text>
</View>
{/* 注意事项 */}
<View style={styles.noteSection}>
<Text style={styles.noteTitle}>注意事项:</Text>
<Text style={styles.noteText}>
• ignoreSilentHardwareSwitch 需要设置为 true,网页播放才有声音
</Text>
<Text style={styles.noteText}>
• 需要配置网络权限才能访问网络
</Text>
<Text style={styles.noteText}>
• 部分属性 HarmonyOS 暂不支持
</Text>
<Text style={styles.noteText}>
• 编译需要 DevEco Studio 6.0.0 (API20) 及以上版本
</Text>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
toolbar: {
flexDirection: 'row',
alignItems: 'center',
padding: 10,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
gap: 5,
},
navButton: {
width: 40,
height: 40,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f5f5f5',
borderRadius: 8,
},
disabledButton: {
opacity: 0.3,
},
navButtonText: {
fontSize: 20,
fontWeight: 'bold',
color: '#333',
},
urlInput: {
flex: 1,
height: 40,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 10,
backgroundColor: '#f9f9f9',
fontSize: 14,
},
goButton: {
paddingHorizontal: 15,
paddingVertical: 8,
backgroundColor: '#42a5f5',
borderRadius: 8,
},
goButtonText: {
color: '#fff',
fontSize: 14,
fontWeight: 'bold',
},
progressBarContainer: {
height: 2,
backgroundColor: '#e0e0e0',
},
progressBar: {
height: '100%',
backgroundColor: '#42a5f5',
},
errorContainer: {
padding: 10,
backgroundColor: '#ffebee',
borderBottomWidth: 1,
borderBottomColor: '#ffcdd2',
},
errorText: {
color: '#c62828',
fontSize: 14,
textAlign: 'center',
},
webviewContainer: {
flex: 1,
backgroundColor: '#fff',
},
webview: {
flex: 1,
},
loadingContainer: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(255, 255, 255, 0.8)',
},
loadingText: {
marginTop: 10,
fontSize: 16,
color: '#666',
},
urlDisplay: {
padding: 10,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
urlLabel: {
fontSize: 12,
color: '#666',
marginBottom: 5,
},
urlText: {
fontSize: 14,
color: '#333',
},
buttonContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 10,
gap: 10,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
actionButton: {
paddingHorizontal: 15,
paddingVertical: 10,
backgroundColor: '#42a5f5',
borderRadius: 8,
minWidth: 100,
alignItems: 'center',
},
actionButtonText: {
color: '#fff',
fontSize: 14,
fontWeight: '500',
},
infoSection: {
margin: 10,
padding: 15,
backgroundColor: '#e3f2fd',
borderRadius: 8,
borderLeftWidth: 4,
borderLeftColor: '#42a5f5',
},
infoTitle: {
fontSize: 14,
fontWeight: 'bold',
marginBottom: 8,
color: '#1565c0',
},
infoText: {
fontSize: 13,
color: '#1976d2',
marginBottom: 4,
},
noteSection: {
margin: 10,
padding: 15,
backgroundColor: '#fff3cd',
borderRadius: 8,
borderLeftWidth: 4,
borderLeftColor: '#ffc107',
},
noteTitle: {
fontSize: 14,
fontWeight: 'bold',
marginBottom: 8,
color: '#856404',
},
noteText: {
fontSize: 13,
color: '#856404',
marginBottom: 4,
},
});
export default WebViewDemo;
🎨 实际应用场景
react-native-webview 可以应用于以下实际场景:
- 混合开发: 在原生应用中嵌入 H5 页面
- 在线文档: 查看 PDF、Word 等在线文档
- 第三方登录: 集成微信、支付宝等第三方登录
- 内容展示: 展示富文本、图表等复杂内容
- 广告展示: 加载第三方广告页面
⚠️ 注意事项与最佳实践
1. 网络权限配置
在使用 WebView 之前,需要在 HarmonyOS 的 module.json5 中配置网络权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
2. 重要属性配置
// ✅ 推荐:启用声音播放
<WebView
ignoreSilentHardwareSwitch={true}
// ...
/>
// ✅ 推荐:启用 JavaScript
<WebView
javaScriptEnabled={true}
domStorageEnabled={true}
// ...
/>
// ✅ 推荐:处理加载状态
<WebView
startInLoadingState={true}
onLoadStart={() => setLoading(true)}
onLoadEnd={() => setLoading(false)}
// ...
/>
3. JavaScript 注入
// ✅ 推荐:页面加载完成后注入
<WebView
onLoad={() => {
webViewRef.current?.injectJavaScript(`
// 你的 JavaScript 代码
true;
`);
}}
/>
// ✅ 推荐:页面加载前注入
<WebView
injectedJavaScriptBeforeContentLoaded={`
// 在页面加载前执行的 JavaScript 代码
`}
/>
4. 网页与原生通信
// 在网页中发送消息
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'message',
data: 'hello from web'
}));
// 在 React Native 中接收消息
<WebView
onMessage={(event) => {
const data = JSON.parse(event.nativeEvent.data);
console.log('收到消息:', data);
}}
/>
5. 性能优化
// ✅ 推荐:启用缓存
<WebView
cacheEnabled={true}
// ...
/>
// ✅ 推荐:清除缓存
webViewRef.current?.clearCache(true);
// ✅ 推荐:减少不必要的渲染
6. HarmonyOS 特殊处理
在 HarmonyOS 上,需要注意:
- 声音播放:
ignoreSilentHardwareSwitch需要设置为true,网页播放才有声音 - 编译版本: 需要使用 DevEco Studio 6.0.0 (API20) 及以上版本
- 部分属性: 部分属性 HarmonyOS 暂不支持
- 混合方案: 需要在 ArkTs 侧添加组件名和 WebView 组件
🧪 测试验证
1. Android 平台测试
npm run android
测试要点:
- 测试网页加载
- 测试导航功能
- 验证 JavaScript 注入
- 检查音频播放
2. iOS 平台测试
npm run ios
测试要点:
- 测试网页加载质量
- 验证 JavaScript 执行
- 测试通信功能
- 检查缓存机制
3. HarmonyOS 平台测试
npm run harmony
测试要点:
- 验证网页加载功能
- 测试声音播放(需要设置 ignoreSilentHardwareSwitch)
- 检查 JavaScript 注入
- 验证网页与原生通信
4. 常见问题排查
问题 1: 网页无法加载
- 检查网络权限配置
- 确认 URL 是否正确
- 验证网络连接
问题 2: 音频没有声音
- 确认
ignoreSilentHardwareSwitch设置为true - 检查设备音量设置
- 验证音频文件格式
问题 3: JavaScript 不执行
- 确认
javaScriptEnabled设置为true - 检查 JavaScript 代码语法
- 验证注入时机
📊 对比:原生 WebView vs react-native-webview
| 特性 | 原生 WebView | react-native-webview |
|---|---|---|
| 跨平台一致性 | ❌ | ✅ 完全一致 |
| API 简洁性 | ⚠️ 复杂 | ✅ 简洁 |
| JavaScript 注入 | ✅ 支持 | ✅ 支持 |
| 网页通信 | ⚠️ 复杂 | ✅ 简单 |
| 导航控制 | ✅ 完整 | ✅ 完整 |
| 缓存管理 | ✅ 完整 | ✅ 完整 |
📝 总结
通过集成 react-native-webview,我们为项目添加了强大的 WebView 功能。这个库提供了完整的网页加载和交互解决方案,支持多种配置选项,并且完全跨平台兼容。
关键要点回顾
- ✅ 安装依赖:
npm install @react-native-ohos/react-native-webview - ✅ 配置平台: 通过 har 包或直接链接源码,配置 CMakeLists.txt、PackageProvider.cpp、RNPackagesFactory.ts 和 buildCustomComponent
- ✅ 集成代码: 使用
WebView组件 - ✅ 支持功能: 加载 URL、注入 JS、网页通信、导航控制等
- ✅ 重要: 本库使用了混合方案,需要在 ArkTs 侧添加组件名和 WebView 组件
- ✅ 注意: ignoreSilentHardwareSwitch 需要设置为 true,网页播放才有声音
实际效果
- Android: 原生 WebView 体验
- iOS: 高质量的 WebView 体验
- HarmonyOS: 一致的 WebView 体验
已知限制
- ⚠️ 部分属性 HarmonyOS 暂不支持
- ⚠️ 需要使用 DevEco Studio 6.0.0 (API20) 及以上版本
- ⚠️ 中文乱码问题已修复
- ⚠️ 部分属性未实现 HarmonyOS 化
遗留问题
- webview 部分属性未实现 HarmonyOS 化
- webview 部分属性未实现 HarmonyOS 化
- 中文乱码(已修复)
希望这篇教程能帮助你顺利集成 react-native-webview,构建出色的 WebView 体验!
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)