weex、cordova、flutter、react-native、uniapp 对比
https://zhuanlan.zhihu.com/p/103409129
Core Components
最常用的 native 组件
REACT NATIVE UI COMPONENT | ANDROID VIEW | IOS VIEW | WEB ANALOG | DESCRIPTION |
---|---|---|---|---|
<View> |
<ViewGroup> |
<UIView> |
A non-scrollling <div> |
A container that supports layout with flexbox, style, some touch handling, and accessibility controls |
<Text> |
<TextView> |
<UITextView> |
<p> |
Displays, styles, and nests strings of text and even handles touch events |
<Image> |
<ImageView> |
<UIImageView> |
<img> |
Displays different types of images |
<ScrollView> |
<ScrollView> |
<UIScrollView> |
<div> |
A generic scrolling container that can contain multiple components and views |
<TextInput> |
<EditText> |
<UITextField> |
<input type="text"> |
Allows the user to enter text |
基本组件 Basic
- ScrollView: 在 IOS 设置
maximumZoomScale
&minimumZoomScale
可以放大缩小;pagingEnabled
实现 scroll 变整页滑动;默认在 layout 实现上 类似 html 的div{flex: 0, maxHeight: 100vh}
- View
- Text
- Image
- TextInput
- StyleSheet:
StyleSheet.create({ xxx css obj})
- [ImageBackground]: props as
Image
, mean asbackground-image
用户界面 User Interface
TouchableHighlight: 包裹仅一个 ElementNode,点击后 backgroundColor 加深 建议替代为 Pressable
TouchableOpacity: 包裹 children,点击后 backgroundColor 变浅(加大透明度)建议替代为 Pressable
TouchableWithoutFeedback: 包裹仅一个 ElementNode,没有交互 styles and effects 建议替代为 Pressable
Pressable: 包裹 children,使其(该 tag)类似 button 具有按压事件:
onPressIn
&onLongPress
&onPressOut
&onPress
等
列表 List Views
- FlatList:
<FlatList data={dataArray} renderItem={renderItem} keyExtractor={item => item.id} onPress={fn} />
内部实现了虚拟列表 virtual-scrolling - SectionList:
<SectionList renderSectionHeader={renderHeader} sections={dataArrayNested} renderItem={renderItem} keyExtractor={item => item.id} onPress={fn} />
相比 FlatList 多了 header 和一层分组 - VirtualizedList:
性能上:因为虚拟列表的原因每次 scroll 都是新的 item render 尽量避免在renderItem
中计算;在renderItemComp
内尽量拆分 props;renderItemComp extends PureComponent
;as simple as possible
安卓特有 Android
- API - BackHandler:
BackHandler.addEventListener('target', function(){ return true/false})
订阅栈 监听用户后退点击物理按键后退键动作,后 register 的先 trigger return true 即 preventDefault 安卓退出操作 - DrawerLayoutAndroid: rendered with renderNavigationView and direct children are the main view (where your content goes).
- API - PermissionsAndroid:
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA, optionalObj); if (granted === PermissionsAndroid.RESULTS.GRANTED){...}
所有可选权限 - API - ToastAndroid: 安卓原生提示冒泡框
ToastAndroid.showWithGravity('msg', ToastAndroid.SHORT, ToastAndroid.CENTER)
,命令式 改 组件式 调用 例子 - TouchableNativeFeedback: 安卓原生按钮 建议替代为 Pressable
ios 特有 IOS
- API - ActionSheettIOS: IOS 的下弹选项列
ActionSheetIOS.showActionSheetWithOptions(options, callback)
- SafeAreaView: 解决 刘海屏等 safe area boundaries 适配问题
- InputAccessoryView: 一个只在出现输入法的情况下才显示的 toolbar,
InputAccessoryView的nativeID
对应TextInput的inputAccessoryViewID
对其进行操作
其他
- ActivityIndicator: loading icon
- Alert:
Alert.alert(title, message?, buttonsConfigArray?, options?)
- Animated: using
Animated.timing()
updatesAnimated.Value
, 例子:const fadeAnim = useRef(new Animated.Value(0)).current; const fadeIn = () => { Animated.timing(fadeAnim, {toValue: 1, duration: 1000}).start() }; const fadeOut = () => { Animated.timing(fadeAnim, {toValue: 0, duration: 1000}).start() }
- Dimensions:
Dimensions.addEventListener("change", ({ window, screen })=>{ setDimensions({ window, screen }) })
,Dimensions.get('window').height
这里的 window 更推荐使用useWindowDimensions
- KeyboardAvoidingView: 当自带输入法出现时,该 view 自动收缩 based on the keyboard height.
<KeyboardAvoidingView><TouchableWithoutFeedback onPress={Keyboard.dismiss}>放置需要根据键盘调整位置的组件</TouchableWithoutFeedback></KeyboardAvoidingView>
配合 flex - Linking: 对应安卓的
Deep Links
和 IOS 的Universal Links
,可以根据 url 跳转其他 app - Modal:
- PixelRatio: 返回设备的像素分辨率 和 缩放大小。
PixelRatio.getPixelSizeForLayoutSize(layoutSize: number): number
返回PixelRatio.get() * layoutSize
把 dp 单位转为 px roundToNearestPixel 相比这个 返回值会 Math.round 取整 - RefreshControl: 刷新 icon
- StatusBar: 控制手机顶端的状态栏,显示隐藏和样式 虽然也有 Imperative API 但是不建议使用 因为全局
一些 native 组件可接受的 style 有一定限制
跨端实现
Platform 模块
Platform.OS
: ‘ios’ / ‘android’Platform.select({key: returnedContent})
: ios / android / native / defaultPlatform.Version
:s- 文件后缀 自动(即 Platform.select 后台进程实现)识别 ‘XX.ios.js’ / ‘XX.android.js’,
import XX from './XX';
Container.js
# picked up by Webpack, Rollup or any other Web bundlerContainer.native.js
# picked up by the React Native bundler for both Android and iOS (Metro), Configure your Web bundler to ignore .native.js 减少 bundle 体积
import { Platform, StyleSheet } from "react-native";
const Component = Platform.select({
ios: () => require("ComponentIOS"),
android: () => require("ComponentAndroid"),
native: () => require("ComponentForNative"),
default: () => require("ComponentForWeb"),
})();
const majorVersionIOS = parseInt(Platform.Version, 10); // 对ios version 取整
return <Component />;
const styles = StyleSheet.create({
container: {
height: Platform.OS === "ios" ? 200 : 100, // 'android'
flex: 1,
...Platform.select({
ios: {
backgroundColor: "red",
},
android: {
backgroundColor: "green",
},
default: {
// other platforms, web for example
backgroundColor: "blue",
},
}),
},
});
开发辅助工具
- 构建方式:
react-native-cli
配合Android Studio
和Xcode
:npm install -g react-native-cli
&react-native init demo
&react-native run-ios
expo
的npm install -g expo-cli
&expo init
&npm run android
- 一个 popular boilerplat 脚手架 模版 ignite
npm i ignite-cli -g
npx ignite-cli new PizzaApp --expo
https://www.jianshu.com/p/cb8dc64e650a - 一个 RN 专用 在线 IDEsnack
- RN 的NPM
- 一个傻瓜教程
- 推荐组件库
- debugger
- 推荐的 IDE
嗯哼
全面屏适配方案:
Dimensions.get('window').height + StatusBar.currentHeight
& 判断纵横比1.8
https://segmentfault.com/a/1190000021258428
rn 的 fetch