准备环境
- volta
$ volta ls
⚡️ Currently active tools:
Node: v16.20.2 (default)
Yarn: v1.22.19 (default)
Tool binaries available:
nrm (default)
- nrm
$ nrm ls
* npm ---------- https://registry.npmjs.org/
yarn --------- https://registry.yarnpkg.com/
tencent ------ https://mirrors.cloud.tencent.com/npm/
cnpm --------- https://r.cnpmjs.org/
taobao ------- https://registry.npmmirror.com/
npmMirror ---- https://skimdb.npmjs.com/registry/
- react-native
$ npx react-native info
...
react-native:
installed: 0.72.6
...
- create-react-native-library
$ npx create-react-native-library --version
0.34.2
创建my-comp
- 创建my-comp
$ npx create-react-native-library my-comp
✔ What is the name of the npm package? … react-native-my-comp
✔ What is the description for the package? … My component
✔ What is the name of package author? … Sunbreak
✔ What is the email address for the package author? … sunbreak.wang@gmail.com
✔ What is the URL for the package author? … https://github.com/Sunbreak
✔ What is the URL for the repository? … https://github.com/Sunbreak/react-native-my-comp
✔ What type of library do you want to develop? › Native view
✔ Which languages do you want to use? › Java & Objective-C
✔ Project created successfully at my-comp!
- 初始化my-comp
$ cd my-comp
$ yarn
- Android运行my-comp
$ yarn example start &
$ yarn example android
- iOS运行my-comp
$ yarn example start &
$ yarn example ios
开启Fabric
- 开启Android Fabric
$ yarn example start &
$ yarn example android --extra-params "-PnewArchEnabled=true"
- 开启iOS Fabric
$ pushd example/ios; RCT_NEW_ARCH_ENABLED=1 pod install; popd
$ yarn example start &
$ yarn example ios
适配Fabric
适配JS/TS
- 添加MyCompViewNativeComponent.ts到
src文件夹
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
interface NativeProps extends ViewProps {
color?: string;
}
export default codegenNativeComponent<NativeProps>('MyCompView');
- 修改index.tsx
export { default as MyCompView } from './MyCompViewNativeComponent';
export * from './MyCompViewNativeComponent';
- 添加codegenConfig到
package.json
+ },
+ "codegenConfig": {
+ "name": "RNMyCompViewSpec",
+ "type": "components",
+ "jsSrcsDir": "src"
}
}
适配Android
- 修改MyCompViewManager.java
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
+import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.annotations.ReactProp;
+import com.facebook.react.viewmanagers.MyCompViewManagerDelegate;
+import com.facebook.react.viewmanagers.MyCompViewManagerInterface;
-public class MyCompViewManager extends SimpleViewManager<View> {
+public class MyCompViewManager extends SimpleViewManager<View> implements MyCompViewManagerInterface<View> {
public static final String REACT_CLASS = "MyCompView";
+ private final MyCompViewManagerDelegate mDelegate;
+
+ public MyCompViewManager() {
+ mDelegate = new MyCompViewManagerDelegate(this);
+ }
+
+ @Override
+ @Nullable
+ protected ViewManagerDelegate<View> getDelegate() {
+ return mDelegate;
+ }
...
+ @Override
@ReactProp(name = "color")
public void setColor(View view, String color) {
view.setBackgroundColor(Color.parseColor(color));
}
适配iOS
MyCompViewManager.m改名为MyCompViewManager.mm,并修改内容
#import <React/RCTViewManager.h>
#import <React/RCTUIManager.h>
#import "RCTBridge.h"
@interface MyCompViewManager : RCTViewManager
@end
@implementation MyCompViewManager
RCT_EXPORT_MODULE(MyCompView)
RCT_EXPORT_VIEW_PROPERTY(color, NSString)
@end
- 添加
MyCompView.h
// This guard prevent this file to be compiled in the old architecture.
#ifdef RCT_NEW_ARCH_ENABLED
#import <React/RCTViewComponentView.h>
#import <UIKit/UIKit.h>
#ifndef MyCompViewNativeComponent_h
#define MyCompViewNativeComponent_h
NS_ASSUME_NONNULL_BEGIN
@interface MyCompView : RCTViewComponentView
@end
NS_ASSUME_NONNULL_END
#endif /* MyCompViewNativeComponent_h */
#endif /* RCT_NEW_ARCH_ENABLED */
- 添加
MyCompView.mm
#import "MyCompView.h"
#import <react/renderer/components/RNMyCompViewSpec/ComponentDescriptors.h>
#import <react/renderer/components/RNMyCompViewSpec/EventEmitters.h>
#import <react/renderer/components/RNMyCompViewSpec/Props.h>
#import <react/renderer/components/RNMyCompViewSpec/RCTComponentViewHelpers.h>
#import "RCTFabricComponentsPlugins.h"
using namespace facebook::react;
@interface MyCompView () <RCTMyCompViewViewProtocol>
@end
@implementation MyCompView {
UIView * _view;
}
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<MyCompViewComponentDescriptor>();
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const MyCompViewProps>();
_props = defaultProps;
_view = [[UIView alloc] init];
self.contentView = _view;
}
return self;
}
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
const auto &oldViewProps = *std::static_pointer_cast<MyCompViewProps const>(_props);
const auto &newViewProps = *std::static_pointer_cast<MyCompViewProps const>(props);
if (oldViewProps.color != newViewProps.color) {
NSString * colorToConvert = [[NSString alloc] initWithUTF8String: newViewProps.color.c_str()];
[_view setBackgroundColor:[self hexStringToColor:colorToConvert]];
}
[super updateProps:props oldProps:oldProps];
}
Class<RCTComponentViewProtocol> MyCompViewCls(void)
{
return MyCompView.class;
}
- hexStringToColor:(NSString *)stringToConvert
{
NSString *noHashString = [stringToConvert stringByReplacingOccurrencesOfString:@"#" withString:@""];
NSScanner *stringScanner = [NSScanner scannerWithString:noHashString];
unsigned hex;
if (![stringScanner scanHexInt:&hex]) return nil;
int r = (hex >> 16) & 0xFF;
int g = (hex >> 8) & 0xFF;
int b = (hex) & 0xFF;
return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:1.0f];
}
@end
测试适配结果
参考“开启Fabric”