我正在尝试创建一个Fabric
组件。我已经让它大部分工作了。我面临的唯一问题是我无法获得点击侦听器为fabric
组件工作。
我创建了一个规范文件
import type {HostComponent, ViewProps} from 'react-native';
import type {DirectEventHandler} from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
type Event = Readonly<{
value: string;
}>;
interface NativeProps extends ViewProps {
text: string;
onClickHandler?: BubblingEventHandler<Event>; ////Event name should start with on
}
export default codegenNativeComponent<NativeProps>(
'MyButtonView',
) as HostComponent<NativeProps>;
对于android
,我的fabric
分量如下所示
public class MyButtonView extends androidx.appcompat.widget.AppCompatButton {
public MyButtonView(Context context) {
super(context);
configureViews();
}
private void configureViews(){
setBackgroundColor(Color.YELLOW);
setOnClickListener(view -> {
onReceiveNativeEvent();
});
}
public void onReceiveNativeEvent() {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTModernEventEmitter.class)
.receiveEvent(getId(),getId(),"onClickHandler",true,0,event,1);
}
}
不确定在receiveEvent
中传递first param as int
,canCoalesceEvent
,customCoalesceKey
和category
在ViewManager
中,我也添加了以下代码
@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
Log.i("here55","999999");
return MapBuilder.of("onClickHandler",
MapBuilder.of("registrationName", "onClickHandler")
);
}
对于android
,我没有从native
android
到js
侧获得callback
我遵循https://reactnative.dev/docs/native-components-android,但它是旧的架构,我认为不适用fabric
组件
同样的iOS
https://reactnative.dev/docs/native-components-ios,文档不是很有帮助的新架构
iOS
,我创建了header
和objective-c++
文件
通常如果我们想添加属性我们会这样做
RCT_EXPORT_VIEW_PROPERTY(text, NSString)
不确定如何为事件处理程序做
iOS
假设你发布的本地规范是正确的(我不太熟悉TypeScript + Codegen duo)当你在ios/
目录下运行pod install
命令时,Codegen应该在React-Codegen
pod中生成EventEmitters
cpp文件(+头)(你可以看到下面如何在XCode中找到它)
链接到带有Pods结构的截图
你可以在你的Objective-C++
代码中使用这些类来发出事件:
if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::$$NAME OF YOUR EVENT EMITTER TYPE$$>(_eventEmitter)
->onEvent(facebook::react::$$NAME OF YOUR EVENT EMITTER TYPE::OnEvent{.value = $$VALUE$$});
}
参见下面的链接,看看react-native-screens
Flow
中的本地组件规范 obj - c++代码中的事件发射- 屏幕管理器中的事件曝光-我不太确定这一行是否必要,还没有测试出来。 Android
- 要触发编码,只需运行本机构建。
- 定义本地事件类,如下所示
- 查看如何调度事件
- 导出事件类型
确实,文档现在是如此简洁,甚至不确定我是否在使用新的体系结构,但它的工作。
下面是Java风格的Android的步骤。
步骤1 -定义规格
type CustomEvent = Readonly<{
status: string;
}>;
export interface NativeProps extends ViewProps {
onStatusChange?: DirectEventHandler<CustomEvent>;
}
步骤2 -定义事件类
public class CustomEvent extends Event<CustomEvent> {
public static final String EVENT_NAME = "topCustomEvent";
private String status;
CustomEvent(int viewId, String _status) {
super(viewId);
this.status = _status;
}
@Override
public String getEventName() {
return EVENT_NAME;
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
super.dispatch(rctEventEmitter);
}
@Override
protected WritableMap getEventData() {
WritableMap event = Arguments.createMap();
event.putString("status", this.status);
return event;
}
}
步骤3 -通过覆盖其getexporttedcustomdirecteventtypeconstants在ViewManager类中导出/注册事件类型方法。
@Override
public @Nullable
Map getExportedCustomDirectEventTypeConstants() {
Map<String, Object> export = super.getExportedCustomDirectEventTypeConstants();
if (export == null) {
export = MapBuilder.newHashMap();
}
export.put(CustomEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStatusChange"));
return export;
}
步骤4-创建dispatchEvent方法,在需要将事件传递给JS的地方调用它。
private void dispatchEvent(String status) {
EventDispatcher mEventDispatcher = UIManagerHelper.getEventDispatcherForReactTag((ReactContext)this.ctx, getId());
mEventDispatcher.dispatchEvent(new CustomEvent(getId(), status));
}
步骤5 -在JS中设置回调,其中事件将被处理。
onStatusChange={(event) => {console.log('ontatusChange: '+event.nativeEvent.status);}}
步骤6 -构建App, codgen应该像这里解释的那样发生。