我们需要“尽可能地复用代码”。
对于一个小组件来说,我们有大量的跨平台的逻辑是重合的:都是显示文本的按钮,都有 active,hover 状态,他们之间唯一的差别就在于视觉样式上的轻微的差别。所以最好的方式是使用同一个组件,然后在必要的地方,用控制语句来区别。
示例代码:
class Segment extends React.Component {
props: {
value: string;
isSelected: boolean;
selectionColor: string;
onPress: () => void;
};
render() {
var selectedButtonStyle;
if (this.props.isSelected) {
selectedButtonStyle = { borderColor: this.props.selectionColor };
}
var deselectedLabelStyle;
if (!this.props.isSelected && Platform.OS === 'android') {
deselectedLabelStyle = styles.deselectedLabel;
}
var title = this.props.value && this.props.value.toUpperCase();
var accessibilityTraits = ['button'];
if (this.props.isSelected) {
accessibilityTraits.push('selected');
}
return (
<TouchableOpacity
accessibilityTraits={accessibilityTraits}
activeOpacity={0.8}
onPress={this.props.onPress}
style={[styles.button, selectedButtonStyle]}>
<Text style={[styles.label, deselectedLabelStyle]}>
{title}
</Text>
</TouchableOpacity>
);
}
}
在这里,我们使用 React Native 的 Platform module,根据代码在不同的平台上运行,应用不同的样式。在这两个平台上,tab 按钮先使用同样的样式,然后分化
var styles = F8StyleSheet.create({
container: {
flexDirection: 'row',
backgroundColor: 'transparent',
ios: {
paddingBottom: 6,
justifyContent: 'center',
alignItems: 'center',
},
android: {
paddingLeft: 60,
},
},
button: {
borderColor: 'transparent',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'transparent',
ios: {
height: HEIGHT,
paddingHorizontal: 20,
borderRadius: HEIGHT / 2,
borderWidth: 1,
},
android: {
paddingBottom: 6,
paddingHorizontal: 10,
borderBottomWidth: 3,
marginRight: 10,
},
},
label: {
letterSpacing: 1,
fontSize: 12,
color: 'white',
},
deselectedLabel: {
color: 'rgba(255, 255, 255, 0.7)',
},
});
这里,我们使用一个改造后的 React Native StyleSheet
API,可根据平台进行一下选择转换:
export function create(styles: Object): {[name: string]: number} {
const platformStyles = {};
Object.keys(styles).forEach((name) => {
let {ios, android, ...style} = {...styles[name]};
if (ios && Platform.OS === 'ios') {
style = {...style, ...ios};
}
if (android && Platform.OS === 'android') {
style = {...style, ...android};
}
platformStyles[name] = style;
});
return StyleSheet.create(platformStyles);
}
现在,我们可以在 app 中复用这个组件了,并且,UI 样式是对 iOS 和 Android 适配的。
----------------------我是分割线-------------------------
分离复杂的差异
当在两个平台实现一个不仅在 UI 上分化,同时也几乎没有共同业务逻辑的组件时,我们需要采用不同的方式。下面的例子是 app 中的顶级导航菜单:
我们可以看到, iOS 版本使用固定的底部导航,而 Android 则使用侧滑菜单。他们之间在动画,样式,甚至菜单内容本身都存在巨大的差异。比如在 Android 上,有类似 logout 这样的菜单选项。
正确的做法,我们应该使用 React Native 内置的 特定平台下的扩展。这个特性允许我们创建两个不同的组件,其中一个叫
FBTabsView.ios.js
,另外一个叫 FBTabsView.android.js
。React Native 会根据运行的平台自动找到并加载他们。
const FBTabsView= require('./FBTabsView');
网友评论