React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法

一、原生组件回调 JS 层提供的事件方法

比如 TextInput 组件 onChangeText 属性,输入事件是发生在原生层的但是需要通知 JS 层发生了变化,并执行 JS 层的方法。

1、给原生组件添加一个按钮用于触发原生事件方法

在 XML 中添加一个按钮

React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法_第1张图片

为了方便让 InfoView 的类,继承自 LinearLayout 类并实现 View.OnClickListener 点击事件处理的接口,就可以在点击时执行特定的逻辑。

public class InfoView extends LinearLayout implements View.OnClickListener {

}

React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法_第2张图片
到这里就已经完成了原生事件的编写,可以点击按钮切换头像的形状。但是原生事件执行了 JS 层现在并不知道这件事已经发生了。

2、告诉 JS 层发生了切换形状的事件,并传入事件参数告知是什么形状

// 创建一个可写的事件参数映射
WritableMap eventParams = Arguments.createMap();
eventParams.putString("shape", this.shape);
// 获取当前视图的 ReactContext
ReactContext context = (ReactContext) getContext();
// 通过 ReactContext 获取 RCTEventEmitter 模块并使用 receiveEvent 方法发送事件
context.getJSModule(RCTEventEmitter.class).receiveEvent(getId(), "onShapeChange", eventParams);

React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法_第3张图片

所有的视图、属性、事件都必须经过 InfoViewManager 进行管理,还需要在 InfoViewManger 中管理该事件。

    @Nullable
    @Override
    public Map getExportedCustomBubblingEventTypeConstants() {
        return MapBuilder.builder()
            .put("onShapeChange",
                    MapBuilder.of("phasedRegistrationNames",
                            MapBuilder.of("bubbled", "onShapeChange")
                    )
            )
            // to-do 继续 put
            .build();
    }

React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法_第4张图片

getExportedCustomBubblingEventTypeConstants 方法返回一个映射,其中包含了你自定义冒泡事件类型的信息。在这里定义了一个名为 “onShapeChange” 的事件,并将其关联到 “onShapeChange” 冒泡阶段。

这是一个相对固定的写法,只需替换 “onShapeChange” 为自定义事件名。这样在 JavaScript 层就可以监听和处理这个自定义冒泡事件。

3、在业务使用该时事件回调

React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法_第5张图片

效果:

二、公开原生组件方法给 JS 层调用

export default () => {

    const ref  = useRef(null);

    useEffect(() => {
        setTimeout(() => {
            sendCommand('setShape', ['round']);
        }, 3000);
    }, []);

    const sendCommand = (command: string, params: any[]) => {
        const viewId = findNodeHandle(ref.current);
        // @ts-ignore
        const commands = UIManager.NativeInfoView.Commands[command].toString();
        UIManager.dispatchViewManagerCommand(viewId, commands, params);
    }

    return (
        <NativeInfoView
            ref={ref}
            style={styles.infoView}
            avatar={avatarUri}
            desc="xxx"
            onShapeChange={(e: any) => {
                console.log(e.nativeEvent.shape);
            }}
        />
    );
}

receiveCommand 方法是 React Native 中用于处理来自 JavaScript 层的命令(commands)的方法。

InfoViewManager.java

public class InfoViewManager extends SimpleViewManager<InfoView> {

    @Nullable
    @Override
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of("setShape", SET_SHAPE_CODE);
    }

    @Override
    public void receiveCommand( @NonNull InfoView view, String commandId, @Nullable ReadableArray args) {
        int command = Integer.parseInt(commandId);
        if (command == SET_SHAPE_CODE) {
            if (args != null && args.size() > 0) {
                String shape = args.getString(0);
                view.setShape(shape);
            }
        } else {
            // TODO
            super.receiveCommand(view, commandId, args);
        }
    }

    public static final int SET_SHAPE_CODE = 100;
}

InfoView.java

    public void setShape(String shape) {
        this.shape = shape;
        Glide.with(this)
                .load(this.url)
                .transform(shape == "circle"
                        ? new CircleCrop()
                        : new RoundedCorners(30)
                )
                .into(avatarImg);
    }

你可能感兴趣的:(React,Native,react,native,javascript,react.js)