React Native跨平台鸿蒙开发高级应用原理:RNOH架构整体架构设计原理
React Native for OpenHarmony(RNOH)架构解析 RNOH是基于React Native新架构(0.68+)的鸿蒙适配版本,采用分层设计: 通信架构 通过JSI实现JavaScript与CPP高效通信 采用C-API直接调用鸿蒙原生能力 TurboModule支持异步原生调用 线程模型 三线程设计:主线程(UI)、JS线程、后台线程 主线程负责ArkUI组件管理和事件处
架构介绍
关于 RN 的架构,可以参考React Native中文网。
RNOH架构

如图,React Native for OpenHarmony 在 React Native 的新架构(0.68 以及之后的版本)的基础上,进行了鸿蒙化的适配。按照功能可以进行如下的划分:
- RN 应用代码:开发者实现的业务代码。
- RN 库代码:在 React Native 供开发者使用的组件和 API 的封装与声明。
- JSI(JavaScript Interface):JavaScript 与 CPP 之间进行通信的 API。
- React Common:所有平台通用的 CPP 代码,用于对 RN 侧传过来的数据进行预处理。
- OpenHarmony 适配代码:接收并处理 React Common 传过来的数据,对接原生的代码,调用 ArkUI 的原生组件与 API。主要包括了两个部分:分别是 TurboModule 与 Fabric。
- OS 代码:对接系统底层功能,根据适配层代码传过来的数据进行渲染,或完成对应的功能。
RNOH(React Native for OpenHarmony)是React Native在鸿蒙系统上的定制版本,采用分层架构设计,支持JavaScript与原生代码高效通信。以下是其核心架构特点:
整体架构设计
- 分层架构:分为JavaScript层(React Native逻辑)和原生层(鸿蒙原生能力),通过双线程模型(JS线程与原生线程分离)确保UI流畅性 。
- 四线程模型:包含主线程(处理eTS事件循环)、JS线程(React Native运行时)、后台线程(任务队列)和Worker线程(TurboModule执行),优化性能 。
核心通信机制
-
C-API架构:相比传统Bridge模式,通过C语言接口直接调用鸿蒙原生能力,减少通信开销 。
-
TurboModule:原生模块通过TurboModule实现,支持异步调用(如callHarmonyNativeMethod) 。
开发环境与工程结构
环境要求:
- Node.js ≥16.0.0,npm ≥8.0.0
= DevEco Studio ≥4.0.0,OpenHarmony SDK ≥API14 。
项目结构:
- harmony/:鸿蒙原生代码(含entry/主模块、oh_modules/依赖)
- src/:JS业务代码
- metro.config.js:配置鸿蒙打包规则 。
React Native线程模型

RNOH线程模型,RNOH的线程一共有3个:
enum TaskThread {
MAIN = 0, // main thread running the eTS event loop
JS, // React Native's JS runtime thread
BACKGROUND, // background tasks queue
};
MAIN/UI线程
RN业务主线程,也是应用主线,应用UI线程。该线程在应用中有唯一实例。
RN在MAIN线程中主要承担的业务功能是:
- ArkUI组件的生命周期管理:CREATE, UPDATE, INSERT, REMOVE, DELETE;
- ArkUI组件树管理;
- RN TurboModule业务功能运行;
- 交互事件、消息处理。

JS线程
JS线程通过虚拟机执行React(JS)代码,通过React代码与RN Common的核心代码交互完成React Native的Render阶段任务。
RN在JS线程中主要承担的业务功能是:
- 加载Bundle,执行Bundle依赖的React代码和Bundle的业务代码。
- 由React业务代码驱动,创建RN ShadowTree,设置ShadowTree的属性。
- 利用Yoga引擎进行组件布局,文本测量和布局。
- 比较完成布局的新、老ShadowTree,生成差异结果mutations。将mutations提交到MAIN线程触发Native的显示刷新。
交互事件、消息处理。
JS线程与RNInstance的实例绑定,有多个RNInstance,则有多个对应的JS线程。
BACKGROUND线程
BACKGROUND线程是RN的实验特性,开启BACKGROUND线程后,会将JS线程的部分布局、ShadowTree比较的任务迁移到该线程执行,从而降低JS线程的负荷。
由于开启BACKGROUND涉及复杂的线程间通信,在稳定性方面带来风险,因此正式商用版本中不要开启BACKGROUND线程。
RNOH线程的长期演进
MAIN线程和JS线程承担了RN框架的全部业务,在重载情况下可能会造成性能瓶颈。RN的业务也受同线程的其他应用代码的影响,造成执行延迟或阻塞等问题。
在长期演进时,可以考虑进行线程扩展:
- 增加唯一TM线程,将TurboModule的业务代码放到TM线程来执行,从而降低MAIN线程负荷。
- 增加单独的TIMER线程,确保时间基准稳定执行。
实际案例参考:
function loadModuleImplementation(moduleId, module) {
if (!module && moduleDefinersBySegmentID.length > 0) {
var _definingSegmentByMod;
var segmentId = (_definingSegmentByMod = definingSegmentByModuleID.get(moduleId)) != null ? _definingSegmentByMod : 0;
var definer = moduleDefinersBySegmentID[segmentId];
if (definer != null) {
definer(moduleId);
module = modules.get(moduleId);
definingSegmentByModuleID.delete(moduleId);
}
}
var nativeRequire = global.nativeRequire;
if (!module && nativeRequire) {
var _unpackModuleId = unpackModuleId(moduleId),
_segmentId = _unpackModuleId.segmentId,
localId = _unpackModuleId.localId;
nativeRequire(localId, _segmentId);
module = modules.get(moduleId);
}
if (!module) {
throw unknownModuleError(moduleId);
}
if (module.hasError) {
throw module.error;
}
if (__DEV__) {
var Systrace = requireSystrace();
var Refresh = requireRefresh();
}
module.isInitialized = true;
var _module = module,
factory = _module.factory,
dependencyMap = _module.dependencyMap;
if (__DEV__) {
initializingModuleIds.push(moduleId);
}
try {
if (__DEV__) {
Systrace.beginEvent("JS_require_" + (module.verboseName || moduleId));
}
var moduleObject = module.publicModule;
if (__DEV__) {
moduleObject.hot = module.hot;
var prevRefreshReg = global.$RefreshReg$;
var prevRefreshSig = global.$RefreshSig$;
if (Refresh != null) {
var RefreshRuntime = Refresh;
global.$RefreshReg$ = function (type, id) {
var prefixedModuleId = __METRO_GLOBAL_PREFIX__ + " " + moduleId + " " + id;
RefreshRuntime.register(type, prefixedModuleId);
};
global.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
}
}
moduleObject.id = moduleId;
factory(global, metroRequire, metroImportDefault, metroImportAll, moduleObject, moduleObject.exports, dependencyMap);
if (!__DEV__) {
module.factory = undefined;
module.dependencyMap = undefined;
}
if (__DEV__) {
Systrace.endEvent();
if (Refresh != null) {
var prefixedModuleId = __METRO_GLOBAL_PREFIX__ + " " + moduleId;
registerExportsForReactRefresh(Refresh, moduleObject.exports, prefixedModuleId);
}
}
return moduleObject.exports;
} catch (e) {
module.hasError = true;
module.error = e;
module.isInitialized = false;
module.publicModule.exports = undefined;
throw e;
} finally {
if (__DEV__) {
if (initializingModuleIds.pop() !== moduleId) {
throw new Error("initializingModuleIds is corrupt; something is terribly wrong");
}
global.$RefreshReg$ = prevRefreshReg;
global.$RefreshSig$ = prevRefreshSig;
}
}
}
function unknownModuleError(id) {
var message = 'Requiring unknown module "' + id + '".';
if (__DEV__) {
message += " If you are sure the module exists, try restarting Metro. " + "You may also want to run `yarn` or `npm install`.";
}
return Error(message);
}
if (__DEV__) {
metroRequire.Systrace = {
beginEvent: function beginEvent() {},
endEvent: function endEvent() {}
};
metroRequire.getModules = function () {
return modules;
};
var createHotReloadingObject = function createHotReloadingObject() {
var hot = {
_acceptCallback: null,
_disposeCallback: null,
_didAccept: false,
accept: function accept(callback) {
hot._didAccept = true;
hot._acceptCallback = callback;
},
dispose: function dispose(callback) {
hot._disposeCallback = callback;
}
};
return hot;
};
var reactRefreshTimeout = null;
var metroHotUpdateModule = function metroHotUpdateModule(id, factory, dependencyMap, inverseDependencies) {
var mod = modules.get(id);
if (!mod) {
if (factory) {
return;
}
throw unknownModuleError(id);
}
if (!mod.hasError && !mod.isInitialized) {
mod.factory = factory;
mod.dependencyMap = dependencyMap;
return;
}
var Refresh = requireRefresh();
var refreshBoundaryIDs = new Set();
var didBailOut = false;
var updatedModuleIDs;
try {
updatedModuleIDs = topologicalSort([id], function (pendingID) {
var pendingModule = modules.get(pendingID);
if (pendingModule == null) {
return [];
}
var pendingHot = pendingModule.hot;
if (pendingHot == null) {
throw new Error("[Refresh] Expected module.hot to always exist in DEV.");
}
var canAccept = pendingHot._didAccept;
if (!canAccept && Refresh != null) {
var isBoundary = isReactRefreshBoundary(Refresh, pendingModule.publicModule.exports);
if (isBoundary) {
canAccept = true;
refreshBoundaryIDs.add(pendingID);
}
}
if (canAccept) {
return [];
}
var parentIDs = inverseDependencies[pendingID];
if (parentIDs.length === 0) {
performFullRefresh("No root boundary", {
source: mod,
failed: pendingModule
});
didBailOut = true;
return [];
}
return parentIDs;
}, function () {
return didBailOut;
}).reverse();
} catch (e) {
if (e === CYCLE_DETECTED) {
performFullRefresh("Dependency cycle", {
source: mod
});
return;
}
throw e;
}
if (didBailOut) {
return;
}
var seenModuleIDs = new Set();
for (var i = 0; i < updatedModuleIDs.length; i++) {
var updatedID = updatedModuleIDs[i];
if (seenModuleIDs.has(updatedID)) {
continue;
}
seenModuleIDs.add(updatedID);
var updatedMod = modules.get(updatedID);
if (updatedMod == null) {
throw new Error("[Refresh] Expected to find the updated module.");
}
var prevExports = updatedMod.publicModule.exports;
var didError = runUpdatedModule(updatedID, updatedID === id ? factory : undefined, updatedID === id ? dependencyMap : undefined);
var nextExports = updatedMod.publicModule.exports;
if (didError) {
return;
}
if (refreshBoundaryIDs.has(updatedID)) {
var isNoLongerABoundary = !isReactRefreshBoundary(Refresh, nextExports);
var didInvalidate = shouldInvalidateReactRefreshBoundary(Refresh, prevExports, nextExports);
if (isNoLongerABoundary || didInvalidate) {
var parentIDs = inverseDependencies[updatedID];
if (parentIDs.length === 0) {
performFullRefresh(isNoLongerABoundary ? "No longer a boundary" : "Invalidated boundary", {
source: mod,
failed: updatedMod
});
return;
}
for (var j = 0; j < parentIDs.length; j++) {
var parentID = parentIDs[j];
var parentMod = modules.get(parentID);
if (parentMod == null) {
throw new Error("[Refresh] Expected to find parent module.");
}
var canAcceptParent = isReactRefreshBoundary(Refresh, parentMod.publicModule.exports);
if (canAcceptParent) {
refreshBoundaryIDs.add(parentID);
updatedModuleIDs.push(parentID);
} else {
performFullRefresh("Invalidated boundary", {
source: mod,
failed: parentMod
});
return;
}
}
}
}
}
if (Refresh != null) {
if (reactRefreshTimeout == null) {
reactRefreshTimeout = setTimeout(function () {
reactRefreshTimeout = null;
Refresh.performReactRefresh();
}, 30);
}
}
};
var topologicalSort = function topologicalSort(roots, getEdges, earlyStop) {
var result = [];
var visited = new Set();
var stack = new Set();
function traverseDependentNodes(node) {
if (stack.has(node)) {
throw CYCLE_DETECTED;
}
if (visited.has(node)) {
return;
}
visited.add(node);
stack.add(node);
var dependentNodes = getEdges(node);
if (earlyStop(node)) {
stack.delete(node);
return;
}
dependentNodes.forEach(function (dependent) {
traverseDependentNodes(dependent);
});
stack.delete(node);
result.push(node);
}
roots.forEach(function (root) {
traverseDependentNodes(root);
});
return result;
};
var runUpdatedModule = function runUpdatedModule(id, factory, dependencyMap) {
var mod = modules.get(id);
if (mod == null) {
throw new Error("[Refresh] Expected to find the module.");
}
var hot = mod.hot;
if (!hot) {
throw new Error("[Refresh] Expected module.hot to always exist in DEV.");
}
if (hot._disposeCallback) {
try {
hot._disposeCallback();
} catch (error) {
console.error(`Error while calling dispose handler for module ${id}: `, error);
}
}
if (factory) {
mod.factory = factory;
}
if (dependencyMap) {
mod.dependencyMap = dependencyMap;
}
mod.hasError = false;
mod.error = undefined;
mod.importedAll = EMPTY;
mod.importedDefault = EMPTY;
mod.isInitialized = false;
var prevExports = mod.publicModule.exports;
mod.publicModule.exports = {};
hot._didAccept = false;
hot._acceptCallback = null;
hot._disposeCallback = null;
metroRequire(id);
if (mod.hasError) {
mod.hasError = false;
mod.isInitialized = true;
mod.error = null;
mod.publicModule.exports = prevExports;
return true;
}
if (hot._acceptCallback) {
try {
hot._acceptCallback();
} catch (error) {
console.error(`Error while calling accept handler for module ${id}: `, error);
}
}
return false;
};
var performFullRefresh = function performFullRefresh(reason, modules) {
if (typeof window !== "undefined" && window.location != null && typeof window.location.reload === "function") {
window.location.reload();
} else {
var Refresh = requireRefresh();
if (Refresh != null) {
var _modules$source$verbo, _modules$source, _modules$failed$verbo, _modules$failed;
var sourceName = (_modules$source$verbo = (_modules$source = modules.source) == null ? void 0 : _modules$source.verboseName) != null ? _modules$source$verbo : "unknown";
var failedName = (_modules$failed$verbo = (_modules$failed = modules.failed) == null ? void 0 : _modules$failed.verboseName) != null ? _modules$failed$verbo : "unknown";
Refresh.performFullRefresh(`Fast Refresh - ${reason} <${sourceName}> <${failedName}>`);
} else {
console.warn("Could not reload the application after an edit.");
}
}
};
var isReactRefreshBoundary = function isReactRefreshBoundary(Refresh, moduleExports) {
if (Refresh.isLikelyComponentType(moduleExports)) {
return true;
}
if (moduleExports == null || typeof moduleExports !== "object") {
return false;
}
var hasExports = false;
var areAllExportsComponents = true;
for (var key in moduleExports) {
hasExports = true;
if (key === "__esModule") {
continue;
}
var desc = Object.getOwnPropertyDescriptor(moduleExports, key);
if (desc && desc.get) {
return false;
}
var exportValue = moduleExports[key];
if (!Refresh.isLikelyComponentType(exportValue)) {
areAllExportsComponents = false;
}
}
return hasExports && areAllExportsComponents;
};
var shouldInvalidateReactRefreshBoundary = function shouldInvalidateReactRefreshBoundary(Refresh, prevExports, nextExports) {
var prevSignature = getRefreshBoundarySignature(Refresh, prevExports);
var nextSignature = getRefreshBoundarySignature(Refresh, nextExports);
if (prevSignature.length !== nextSignature.length) {
return true;
}
for (var i = 0; i < nextSignature.length; i++) {
if (prevSignature[i] !== nextSignature[i]) {
return true;
}
}
return false;
};
var getRefreshBoundarySignature = function getRefreshBoundarySignature(Refresh, moduleExports) {
var signature = [];
signature.push(Refresh.getFamilyByType(moduleExports));
if (moduleExports == null || typeof moduleExports !== "object") {
return signature;
}
for (var key in moduleExports) {
if (key === "__esModule") {
continue;
}
var desc = Object.getOwnPropertyDescriptor(moduleExports, key);
if (desc && desc.get) {
continue;
}
var exportValue = moduleExports[key];
signature.push(key);
signature.push(Refresh.getFamilyByType(exportValue));
}
return signature;
};
var registerExportsForReactRefresh = function registerExportsForReactRefresh(Refresh, moduleExports, moduleID) {
Refresh.register(moduleExports, moduleID + " %exports%");
if (moduleExports == null || typeof moduleExports !== "object") {
return;
}
for (var key in moduleExports) {
var desc = Object.getOwnPropertyDescriptor(moduleExports, key);
if (desc && desc.get) {
continue;
}
var exportValue = moduleExports[key];
var typeID = moduleID + " %exports% " + key;
Refresh.register(exportValue, typeID);
}
};
global.__accept = metroHotUpdateModule;
}
if (__DEV__) {
var requireSystrace = function requireSystrace() {
return global[__METRO_GLOBAL_PREFIX__ + "__SYSTRACE"] || metroRequire.Systrace;
};
var requireRefresh = function requireRefresh() {
return global[__METRO_GLOBAL_PREFIX__ + "__ReactRefresh"] || global[global.__METRO_GLOBAL_PREFIX__ + "__ReactRefresh"] || metroRequire.Refresh;
};
}
})(typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this);
(function (global) {
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @polyfill
* @nolint
* @format
*/
/* eslint-disable no-shadow, eqeqeq, curly, no-unused-vars, no-void, no-control-regex */
/**
* This pipes all of our console logging functions to native logging so that
* JavaScript errors in required modules show up in Xcode via NSLog.
*/
var inspect = function () {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// https://github.com/joyent/node/blob/master/lib/util.js
function inspect(obj, opts) {
var ctx = {
seen: [],
formatValueCalls: 0,
stylize: stylizeNoColor
};
return formatValue(ctx, obj, opts.depth);
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function (val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
ctx.formatValueCalls++;
if (ctx.formatValueCalls > 200) {
return `[TOO BIG formatValueCalls ${ctx.formatValueCalls} exceeded limit of 200]`;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '',
array = false,
braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function (key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value)) return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = "'" + JSON.stringify(value).replace(/^"|"$/g, '').replace(/'/g, "\\'").replace(/\\"/g, '"') + "'";
return ctx.stylize(simple, 'string');
}
if (isNumber(value)) return ctx.stylize('' + value, 'number');
if (isBoolean(value)) return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value)) return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true));
} else {
output.push('');
}
}
keys.forEach(function (key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || {
value: value[key]
};
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function (prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
function isBoolean(arg) {
return typeof arg === 'boolean';
}
function isNull(arg) {
return arg === null;
}
function isNullOrUndefined(arg) {
return arg == null;
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isString(arg) {
return typeof arg === 'string';
}
function isSymbol(arg) {
return typeof arg === 'symbol';
}
function isUndefined(arg) {
return arg === void 0;
}
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
function isError(e) {
return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error);
}
function isFunction(arg) {
return typeof arg === 'function';
}
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
return inspect;
}();
var OBJECT_COLUMN_NAME = '(index)';
var LOG_LEVELS = {
trace: 0,
info: 1,
warn: 2,
error: 3
};
var INSPECTOR_LEVELS = [];
INSPECTOR_LEVELS[LOG_LEVELS.trace] = 'debug';
INSPECTOR_LEVELS[LOG_LEVELS.info] = 'log';
INSPECTOR_LEVELS[LOG_LEVELS.warn] = 'warning';
INSPECTOR_LEVELS[LOG_LEVELS.error] = 'error';
// Strip the inner function in getNativeLogFunction(), if in dev also
// strip method printing to originalConsole.
var INSPECTOR_FRAMES_TO_SKIP = __DEV__ ? 2 : 1;
function getNativeLogFunction(level) {
return function () {
var str;
if (arguments.length === 1 && typeof arguments[0] === 'string') {
str = arguments[0];
} else {
str = Array.prototype.map.call(arguments, function (arg) {
return inspect(arg, {
depth: 10
});
}).join(', ');
}
// TRICKY
// If more than one argument is provided, the code above collapses them all
// into a single formatted string. This transform wraps string arguments in
// single quotes (e.g. "foo" -> "'foo'") which then breaks the "Warning:"
// check below. So it's important that we look at the first argument, rather
// than the formatted argument string.
var firstArg = arguments[0];
var logLevel = level;
if (typeof firstArg === 'string' && firstArg.slice(0, 9) === 'Warning: ' && logLevel >= LOG_LEVELS.error) {
// React warnings use console.error so that a stack trace is shown,
// but we don't (currently) want these to show a redbox
// (Note: Logic duplicated in ExceptionsManager.js.)
logLevel = LOG_LEVELS.warn;
}
if (global.__inspectorLog) {
global.__inspectorLog(INSPECTOR_LEVELS[logLevel], str, [].slice.call(arguments), INSPECTOR_FRAMES_TO_SKIP);
}
if (groupStack.length) {
str = groupFormat('', str);
}
global.nativeLoggingHook(str, logLevel);
};
}
function repeat(element, n) {
return Array.apply(null, Array(n)).map(function () {
return element;
});
}
打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

最后运行效果图如下显示:


欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐



所有评论(0)