React Native JSI 是 React Native 的一个新特性,它可以实现 RN 与原生端的通信。JSI 基于 C++,所以可以很好地利用移动设备的 CPU 和 GPU 功能,从而提高应用程序的性能和可维护性。
要使用 RN JSI,需要在项目中安装相应的模块和库,例如 Folly 和 TurboModules。接下来,我们将详细讲解如何在 React Native 中实现 JSI 与原生通信的示例代码。
步骤 1:安装依赖模块
在 React Native 项目中,使用 npm 安装 Folly 和 TurboModules 模块:
npm install folly
npm install react-native-turbomodules
步骤 2:创建原生模块
接下来需要创建原生模块,并将其链接到 React Native 应用程序中。我们可以使用 C 语言编写原生模块,因为 JSI 是基于 C++ 的。以下是一个用 C 语言编写的示例原生模块:
#include <jsi/jsi.h>
static jsi::Value toUpperCase(const jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) {
if (count != 1) {
throw jsi::JSError(rt, "Expected one argument");
}
if (!arguments[0].isString()) {
throw jsi::JSError(rt, "Expected a string argument");
}
std::string input = arguments[0].asString(rt).utf8(rt);
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
return jsi::String::createFromUtf8(rt, input);
}
extern "C" {
jsi::HostObjectBinding toUpperCaseBinding([](jsi::Runtime &rt) {
jsi::Object exports(rt);
exports.setProperty(rt, "toUpperCase", jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forAscii(rt, "toUpperCase"), 1, toUpperCase));
return exports;
});
__attribute__((visibility("default"))) jsi::HostObjectBinding *rn_test_toUpperCase_binding_entry() {
return &toUpperCaseBinding;
}
}
以上代码实现了一个名为 toUpperCase
的函数,用于将输入字符串转换为大写形式。这些功能将通过 JSI 转换并从 React Native JavaScript 代码中调用。
步骤 3:创建 JS 代码
接下来,我们将创建 JS 代码,并调用原生模块来转换字符串。以下是一个简单的 React Native JS 代码示例:
import { TurboModuleRegistry } from 'react-native';
const { toUpperCase } = TurboModuleRegistry.get('toUpperCase');
console.log(toUpperCase('hello world')); // 输出 HELLO WORLD
以上代码通过 TurboModuleRegistry
API 获取到 toUpperCase
函数,并使用它将字符串转换为大写形式。现在,您可以在原生代码中使用 toUpperCase
,并在 React Native JavaScript 中调用它了。
示例 1:使用原生模块重新实现 React Native 原生组件
以下是一个基本示例,演示如何使用原生模块重新实现 React Native 的原生组件:
#include <react/renderer/components/view/ViewShadowNode.h>
namespace facebook {
namespace react {
class ViewShadowNodeWithSize: public ViewShadowNode {
public:
ViewShadowNodeWithSize() = default;
void layout(LayoutContext layoutContext) override {
StyleLayoutNode::layout(layoutContext);
auto layoutMetrics = getLayoutMetrics();
layoutMetrics.frame.size.width = 200;
layoutMetrics.frame.size.height = 100;
setLayoutMetrics(layoutMetrics, layoutContext.getLayoutConstraints());
}
static ShadowNode *createTag() {
return new ViewShadowNodeWithSize();
}
};
} // namespace react
} // namespace facebook
extern "C" {
std::shared_ptr<facebook::react::ViewShadowNodeWithSize> rn_test_createautoslizeshadownode() {
return std::make_shared<facebook::react::ViewShadowNodeWithSize>();
}
}
上面的代码是一个可调整大小的 ShadowNode 的增强版本,其大小能够是 200 x 100,这是我们在 layout() 方法中硬编码的。接下来,我们需要编写 JavaScript 代码,来使用该模块创建您的自定义 ShadowNode 的示例:
import { requireNativeComponent } from 'react-native';
const AutoSizedView = requireNativeComponent('AutoSizedView', null);
function App() {
return (
<AutoSizedView style={{flex: 1, backgroundColor: 'blue'}} />
);
}
示例 2:使用原生模块扩展 React Native 功能
以下是一个扩展 RN Navigation 组件的示例,演示如何在原生 C++ 中实现一个更好的导航栏组件:
#include <react/renderer/components/navigation/NavigationShadowNode.h>
#include <react/renderer/components/navigation/NavigationBarShadowNode.h>
#include <react/renderer/components/view/ViewEventEmitter.h>
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/components/view/ViewShadowNode.h>
#include <react/renderer/core/LayoutMetrics.h>
namespace facebook {
namespace react {
class BetterNavbarShadowNode: public NavigationBarShadowNode {
using Super = NavigationBarShadowNode;
public:
BetterNavbarShadowNode() = default;
void layout(LayoutContext layoutContext) override {
auto layoutMetrics = getLayoutMetrics();
layoutMetrics.frame.size.height = 75;
setLayoutMetrics(layoutMetrics, layoutContext.getLayoutConstraints());
Super::layout(layoutContext);
}
void didUpdateProps() override {
Super::didUpdateProps();
auto prop = traitValue("foo");
if (prop && prop->isNumber()) {
auto eventEmitter = getViewShadowNode()->getEventEmitter();
eventEmitter->dispatchEvent("fooChange", folly::dynamic::object("foo", prop->getNumber()));
}
}
static ShadowNode *createTag() {
return new BetterNavbarShadowNode();
}
};
class BetterNavigationShadowNode: public NavigationShadowNode {
using Super = NavigationShadowNode;
public:
BetterNavigationShadowNode() = default;
static ShadowNode *createTag() {
return new BetterNavigationShadowNode();
}
};
} // namespace react
} // namespace facebook
extern "C" {
std::shared_ptr<facebook::react::NavigationShadowNode> rn_test_createBetterNavigation() {
return std::make_shared<facebook::react::BetterNavigationShadowNode>();
}
std::shared_ptr<facebook::react::NavigationBarShadowNode> rn_test_createBetterNavbar() {
return std::make_shared<facebook::react::BetterNavbarShadowNode>();
}
}
上述 C++ 代码是一个改进 React Native Navigation Bar 组件的实现,我们在这里增加了一个名称为 foo
的 trait ,当它的数值被更新时,它将触发自定义事件 fooChange
。现在,我们需要编写 JavaScript 代码来使用该模块:
import { requireNativeComponent } from 'react-native';
const BetterNavbar = requireNativeComponent('BetterNavbar', null);
function App() {
return (
<BetterNavbar style={{ height: 75 }} foo={42} onFooChange={value => console.log(`foo is now ${value}`)} />
);
}
结论
React Native JSI 的功能强大且高效,可以帮助编写更加高效、高性能和可维护的 React Native 应用程序。我们的文本提供了使用 RN JSI 实现与原生通信的示例代码的完整攻略,以及两个示例的详细说明,希望能对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:React Native JSI实现RN与原生通信的示例代码 - Python技术站