在React Native中,开发自定义组件(例如一个Tag组件)通常涉及到创建React组件,并通过JSX在组件中定义其结构、样式和行为。以下是如何开发一个简单的Tag组件的步骤:
步骤 1: 创建组件文件
首先,创建一个新的React组件文件,例如Tag.js。
步骤 2: 定义组件
在Tag.js文件中,你可以定义一个简单的Tag组件。这个组件可以接受一些属性(props),比如文本内容、背景色、字体大小等,并使用这些属性来渲染组件。
javascript
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const Tag = ({ text, style }) => {
return (
<View style={[styles.tagContainer, style]}>
<Text style={styles.tagText}>{text}</Text>
</View>
);
};
const styles = StyleSheet.create({
tagContainer: {
borderRadius: 5,
paddingHorizontal: 10,
paddingVertical: 5,
backgroundColor: '007AFF', // 默认蓝色背景
marginRight: 5, // 一些右外边距,以便多个标签可以水平排列
},
tagText: {
color: 'white', // 默认白色文字
fontSize: 14, // 默认字体大小
}
});
export default Tag;
步骤 3: 使用组件
现在你可以在其他组件或页面中使用Tag组件了。例如,在另一个组件中导入并使用它:
javascript
import React from 'react';
import { View } from 'react-native';
import Tag from './Tag'; // 确保路径正确
const App = () => {
return (
<View>
<Tag text="标签1" />
<Tag text="标签2" style={{ backgroundColor: 'green' }} /> {/* 自定义样式 */}
</View>
);
};
export default App;
扩展功能
你可以根据需要扩展Tag组件的功能,例如添加点击事件处理、不同的标签样式等。例如,添加一个点击事件处理器:
javascript
const Tag = ({ text, style, onPress }) => {
return (
<View style={[styles.tagContainer, style]} onPress={onPress}>
<Text style={styles.tagText}>{text}</Text>
</View>
);
};
然后在使用组件时传递一个点击事件处理器:
javascript
<Tag text="可点击标签" onPress={() => alert('标签被点击了!')} />
这样,你就创建了一个可以自定义样式和行为的Tag组件,并且可以轻松地在React Native应用中使用它。
创建一个Tag组件真实代码演示:
js
// App.tsx
import React, { useState } from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
SafeAreaView,
Image,
Dimensions,
TouchableOpacity,
Pressable
} from 'react-native';
// Base64 Icons for tag components
const TAG_ICONS = {
close: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTAzVDE2OjU1OjQ5KzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMS0wM1QxNjo1NjoxNCswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0wM1QxNjo1NjoxNCswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyZjA5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MmYwOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MmYwOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyZjA5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHN0RXZ0OndoZW49IjIwMTktMDEtMDNUMTY6NTU6NDlaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAA//+gB5ZbAAAJRElEQVRoBe1ZaWxUVRQ+97030+k6U6Z0hk5npksptKW0bFJAWRB3UEFFjQuJKIoLJCZqYhRjNC5RFCMuaKJREhMXjAuKggsuRI0bGkEpWymltNBS2ulMZ9qZmfbe9+699715MzPTmdLS6STnfPPee+fc755zz3nnPcNwHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMx......',
add: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTAzVDE2OjU2OjIwKzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMS0wM1QxNjo1Njo0NSswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0wM1QxNjo1Njo0NSswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyZjE5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MmYxOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MmYxOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyZjE5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHN0RXZ0OndoZW49IjIwMTktMDEtMDNUMTY6NTY6MjBaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAA//+gB5ZbAAAJRElEQVRoBe1ZaWxUVRQ+97030+k6U6Z0hk5npksptKW0bFJAWRB3UEFFjQuJKIoLJCZqYhRjNC5RFCMuaKJREhMXjAuKggsuRI0bGkEpWymltNBS2ulMZ9qZmfbe9+699715MzPTmdLS6STnfPPee+fc755zz3nnPcNwHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMx......',
check: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTAzVDE2OjU2OjUxKzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMS0wM1QxNjo1NzoxNiswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0wM1QxNjo1NzoxNiswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyZjI5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MmYyOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MmYyOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyZjI5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHN0RXZ0OndoZW49IjIwMTktMDEtMDNUMTY6NTY6NTFaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAA//+gB5ZbAAAJRElEQVRoBe1ZaWxUVRQ+97030+k6U6Z0hk5npksptKW0bFJAWRB3UEFFjQuJKIoLJCZqYhRjNC5RFCMuaKJREhMXjAuKggsuRI0bGkEpWymltNBS2ulMZ9qZmfbe9+699715MzPTmdLS6STnfPPee+fc755zz3nnPcNwHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMx......',
star: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTAzVDE2OjU3OjIyKzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMS0wM1QxNjo1Nzo0OCswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0wM1QxNjo1Nzo0OCswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyZjM5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MmYzOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MmYzOWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyZjM5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHN0RXZ0OndoZW49IjIwMTktMDEtMDNUMTY6NTc6MjJaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAA//+gB5ZbAAAJRElEQVRoBe1ZaWxUVRQ+97030+k6U6Z0hk5npksptKW0bFJAWRB3UEFFjQuJKIoLJCZqYhRjNC5RFCMuaKJREhMXjAuKggsuRI0bGkEpWymltNBS2ulMZ9qZmfbe9+699715MzPTmdLS6STnfPPee+fc755zz3nnPcNwHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMx......',
heart: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTAzVDE2OjU3OjUzKzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMS0wM1QxNjo1ODoxOCswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0wM1QxNjo1ODoxOCswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyZjQ5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MmY0OWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MmY0OWNmNDktNWI1ZS1mOTQ3LWI4N2ItMmQzOWI0MTI0MmViIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyZjQ5Y2Y0OS01YjVlLWY5NDctYjg3Yi0yZDM5YjQxMjQyZWIiIHN0RXZ0OndoZW49IjIwMTktMDEtMDNUMTY6NTc6NTNaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAA//+gB5ZbAAAJRElEQVRoBe1ZaWxUVRQ+97030+k6U6Z0hk5npksptKW0bFJAWRB3UEFFjQuJKIoLJCZqYhRjNC5RFCMuaKJREhMXjAuKggsuRI0bGkEpWymltNBS2ulMZ9qZmfbe9+699715MzPTmdLS6STnfPPee+fc755zz3nnPcNwHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMdxHMx......'
};
// 标签组件
interface TagProps {
text: string;
type?: 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'default';
closable?: boolean;
onClose?: () => void;
icon?: string;
size?: 'small' | 'medium' | 'large';
rounded?: boolean;
onPress?: () => void;
}
const Tag: React.FC<TagProps> = ({
text,
type = 'default',
closable = false,
onClose,
icon,
size = 'medium',
rounded = false,
onPress
}) => {
const getTypeStyle = () => {
switch (type) {
case 'primary':
return {
backgroundColor: '#dbeafe',
borderColor: '#3b82f6',
textColor: '#1d4ed8'
};
case 'success':
return {
backgroundColor: '#dcfce7',
borderColor: '#22c55e',
textColor: '#15803d'
};
case 'warning':
return {
backgroundColor: '#fef3c7',
borderColor: '#f59e0b',
textColor: '#b45309'
};
case 'danger':
return {
backgroundColor: '#fee2e2',
borderColor: '#ef4444',
textColor: '#b91c1c'
};
case 'info':
return {
backgroundColor: '#e0f2fe',
borderColor: '#0ea5e9',
textColor: '#0891b2'
};
default:
return {
backgroundColor: '#f3f4f6',
borderColor: '#9ca3af',
textColor: '#4b5563'
};
}
};
const getSizeStyle = () => {
switch (size) {
case 'small':
return {
fontSize: 12,
paddingVertical: 4,
paddingHorizontal: 8,
borderRadius: rounded ? 12 : 4
};
case 'large':
return {
fontSize: 16,
paddingVertical: 8,
paddingHorizontal: 16,
borderRadius: rounded ? 20 : 8
};
default: // medium
return {
fontSize: 14,
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: rounded ? 16 : 6
};
}
};
const typeStyle = getTypeStyle();
const sizeStyle = getSizeStyle();
return (
<Pressable
style={[
styles.tagContainer,
{
backgroundColor: typeStyle.backgroundColor,
borderColor: typeStyle.borderColor,
borderWidth: 1,
borderRadius: sizeStyle.borderRadius
}
]}
onPress={onPress}
>
<View style={styles.tagContent}>
{icon && (
<Image
source={{ uri: icon }}
style={[
styles.tagIcon,
{
width: sizeStyle.fontSize,
height: sizeStyle.fontSize,
tintColor: typeStyle.textColor,
marginRight: 4
}
]}
/>
)}
<Text
style={[
styles.tagText,
{
fontSize: sizeStyle.fontSize,
color: typeStyle.textColor
}
]}
>
{text}
</Text>
</View>
{closable && (
<TouchableOpacity
style={styles.closeButton}
onPress={onClose}
>
<Image
source={{ uri: TAG_ICONS.close }}
style={[
styles.closeIcon,
{
width: sizeStyle.fontSize - 2,
height: sizeStyle.fontSize - 2,
tintColor: typeStyle.textColor
}
]}
/>
</TouchableOpacity>
)}
</Pressable>
);
};
// 标签组组件
interface TagGroupProps {
tags: string[];
type?: TagProps['type'];
closable?: boolean;
onTagClose?: (index: number) => void;
onTagPress?: (index: number) => void;
}
const TagGroup: React.FC<TagGroupProps> = ({
tags,
type = 'default',
closable = false,
onTagClose,
onTagPress
}) => {
return (
<View style={styles.tagGroup}>
{tags.map((tag, index) => (
<View key={index} style={styles.tagGroupItem}>
<Tag
text={tag}
type={type}
closable={closable}
onClose={() => onTagClose && onTagClose(index)}
onPress={() => onTagPress && onTagPress(index)}
/>
</View>
))}
</View>
);
};
// 可编辑标签输入组件
interface EditableTagInputProps {
tags: string[];
onTagsChange: (tags: string[]) => void;
placeholder?: string;
}
const EditableTagInput: React.FC<EditableTagInputProps> = ({
tags,
onTagsChange,
placeholder = '添加标签...'
}) => {
const [inputText, setInputText] = useState('');
const [isFocused, setIsFocused] = useState(false);
const handleAddTag = () => {
if (inputText.trim() && !tags.includes(inputText.trim())) {
onTagsChange([...tags, inputText.trim()]);
setInputText('');
}
};
const handleRemoveTag = (index: number) => {
const newTags = [...tags];
newTags.splice(index, 1);
onTagsChange(newTags);
};
return (
<View style={styles.editableTagContainer}>
<View style={styles.tagInputArea}>
{tags.map((tag, index) => (
<View key={index} style={styles.editableTagItem}>
<Tag
text={tag}
type="primary"
closable
onClose={() => handleRemoveTag(index)}
/>
</View>
))}
<View style={[
styles.tagInputContainer,
isFocused && styles.tagInputContainerFocused
]}>
<TextInput
style={styles.tagInput}
value={inputText}
onChangeText={setInputText}
placeholder={placeholder}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onSubmitEditing={handleAddTag}
/>
<TouchableOpacity
style={styles.addTagButton}
onPress={handleAddTag}
>
<Image
source={{ uri: TAG_ICONS.add }}
style={styles.addTagIcon}
/>
</TouchableOpacity>
</View>
</View>
</View>
);
};
// 主应用组件
const App = () => {
const [selectedTags, setSelectedTags] = useState<string[]>(['React', 'TypeScript']);
const [dynamicTags, setDynamicTags] = useState<string[]>(['前端', '移动端']);
const removeSelectedTag = (index: number) => {
const newTags = [...selectedTags];
newTags.splice(index, 1);
setSelectedTags(newTags);
};
const addDynamicTag = (tag: string) => {
if (!dynamicTags.includes(tag)) {
setDynamicTags([...dynamicTags, tag]);
}
};
const removeDynamicTag = (index: number) => {
const newTags = [...dynamicTags];
newTags.splice(index, 1);
setDynamicTags(newTags);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerTitle}>标签组件演示</Text>
<Text style={styles.headerSubtitle}>现代化标签展示与交互</Text>
</View>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={styles.section}>
<Text style={styles.sectionTitle}>基础标签</Text>
<View style={styles.tagsContainer}>
<Tag text="默认标签" type="default" />
<Tag text="主要标签" type="primary" />
<Tag text="成功标签" type="success" />
<Tag text="警告标签" type="warning" />
<Tag text="危险标签" type="danger" />
<Tag text="信息标签" type="info" />
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>带图标标签</Text>
<View style={styles.tagsContainer}>
<Tag text="收藏" type="warning" icon={TAG_ICONS.star} />
<Tag text="喜欢" type="danger" icon={TAG_ICONS.heart} />
<Tag text="已完成" type="success" icon={TAG_ICONS.check} />
<Tag text="重要" type="primary" icon={TAG_ICONS.star} />
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>可关闭标签</Text>
<View style={styles.tagsContainer}>
{selectedTags.map((tag, index) => (
<Tag
key={index}
text={tag}
type="primary"
closable
onClose={() => removeSelectedTag(index)}
/>
))}
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>不同尺寸标签</Text>
<View style={styles.tagsContainer}>
<Tag text="小标签" size="small" type="primary" />
<Tag text="中标签" size="medium" type="success" />
<Tag text="大标签" size="large" type="warning" />
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>圆角标签</Text>
<View style={styles.tagsContainer}>
<Tag text="圆角标签" rounded type="primary" />
<Tag text="带图标" rounded icon={TAG_ICONS.star} type="success" />
<Tag text="可关闭" rounded closable type="warning" />
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>标签组</Text>
<TagGroup
tags={['设计', '开发', '测试', '部署']}
type="info"
closable
onTagClose={(index) => console.log(`关闭标签: ${index}`)}
onTagPress={(index) => console.log(`点击标签: ${index}`)}
/>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>可编辑标签</Text>
<View style={styles.editableSection}>
<EditableTagInput
tags={dynamicTags}
onTagsChange={setDynamicTags}
placeholder="输入新标签并回车添加"
/>
<View style={styles.suggestedTags}>
<Text style={styles.suggestedTitle}>推荐标签:</Text>
<View style={styles.suggestedTagList}>
{['React Native', '鸿蒙', 'Flutter', '小程序'].map((tag, index) => (
<TouchableOpacity
key={index}
style={styles.suggestedTagButton}
onPress={() => addDynamicTag(tag)}
>
<Text style={styles.suggestedTagText}>{tag}</Text>
</TouchableOpacity>
))}
</View>
</View>
</View>
</View>
<View style={styles.featuresSection}>
<Text style={styles.featuresTitle}>功能特性</Text>
<View style={styles.featureList}>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>六种预设样式(默认、主要、成功、警告、危险、信息)</Text>
</View>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>三种尺寸(小、中、大)</Text>
</View>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>支持圆角和直角样式</Text>
</View>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>可关闭标签功能</Text>
</View>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>支持图标显示</Text>
</View>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>标签组组件</Text>
</View>
<View style={styles.featureItem}>
<Text style={styles.featureBullet}>•</Text>
<Text style={styles.featureText}>可编辑标签输入</Text>
</View>
</View>
</View>
<View style={styles.usageSection}>
<Text style={styles.usageTitle}>使用说明</Text>
<Text style={styles.usageText}>
标签组件用于标记和分类内容,常用于文章标签、商品属性、筛选条件等场景。
提供丰富的样式选项和交互功能,满足多样化的业务需求。
</Text>
</View>
</ScrollView>
<View style={styles.footer}>
<Text style={styles.footerText}>© 2023 标签组件. All rights reserved.</Text>
</View>
</SafeAreaView>
);
};
// TextInput component for editable tags
const TextInput = ({ style, ...props }: any) => (
<View style={[styles.textInputContainer, style]}>
<View style={styles.textInputInner}>
<View style={styles.textInputPlaceholder} />
<View style={styles.textInputCursor} />
</View>
</View>
);
const { width, height } = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff',
},
header: {
backgroundColor: '#f9fafb',
paddingTop: 20,
paddingBottom: 25,
paddingHorizontal: 20,
borderBottomWidth: 1,
borderBottomColor: '#e5e7eb',
},
headerTitle: {
fontSize: 26,
fontWeight: '700',
color: '#1f2937',
textAlign: 'center',
marginBottom: 5,
},
headerSubtitle: {
fontSize: 15,
color: '#6b7280',
textAlign: 'center',
},
contentContainer: {
padding: 20,
},
section: {
marginBottom: 30,
},
sectionTitle: {
fontSize: 22,
fontWeight: '700',
color: '#1f2937',
marginBottom: 20,
paddingLeft: 10,
borderLeftWidth: 4,
borderLeftColor: '#3b82f6',
},
tagsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 10,
},
tagContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
tagContent: {
flexDirection: 'row',
alignItems: 'center',
},
tagText: {
fontWeight: '600',
},
tagIcon: {
marginRight: 4,
},
closeButton: {
marginLeft: 6,
padding: 2,
},
closeIcon: {
tintColor: '#4b5563',
},
tagGroup: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 10,
},
tagGroupItem: {
margin: 2,
},
editableTagContainer: {
backgroundColor: '#f9fafb',
borderRadius: 12,
padding: 15,
borderWidth: 1,
borderColor: '#e5e7eb',
},
tagInputArea: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
gap: 8,
},
editableTagItem: {
margin: 2,
},
tagInputContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#ffffff',
borderRadius: 8,
borderWidth: 1,
borderColor: '#d1d5db',
paddingHorizontal: 10,
paddingVertical: 6,
flex: 1,
minWidth: 120,
},
tagInputContainerFocused: {
borderColor: '#3b82f6',
borderWidth: 2,
},
tagInput: {
flex: 1,
fontSize: 14,
color: '#1f2937',
},
addTagButton: {
padding: 4,
},
addTagIcon: {
width: 16,
height: 16,
tintColor: '#3b82f6',
},
editableSection: {
gap: 20,
},
suggestedTags: {
marginTop: 10,
},
suggestedTitle: {
fontSize: 16,
fontWeight: '600',
color: '#1f2937',
marginBottom: 10,
},
suggestedTagList: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 10,
},
suggestedTagButton: {
backgroundColor: '#e0f2fe',
borderRadius: 16,
paddingHorizontal: 12,
paddingVertical: 6,
borderWidth: 1,
borderColor: '#0ea5e9',
},
suggestedTagText: {
fontSize: 14,
color: '#0891b2',
fontWeight: '500',
},
featuresSection: {
backgroundColor: '#f9fafb',
borderRadius: 16,
padding: 20,
marginBottom: 30,
borderWidth: 1,
borderColor: '#e5e7eb',
},
featuresTitle: {
fontSize: 20,
fontWeight: '700',
color: '#1f2937',
marginBottom: 15,
textAlign: 'center',
},
featureList: {
paddingLeft: 10,
},
featureItem: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 12,
},
featureBullet: {
fontSize: 18,
color: '#3b82f6',
marginRight: 10,
},
featureText: {
fontSize: 16,
color: '#4b5563',
flex: 1,
},
usageSection: {
backgroundColor: '#f9fafb',
borderRadius: 16,
padding: 20,
borderWidth: 1,
borderColor: '#e5e7eb',
},
usageTitle: {
fontSize: 20,
fontWeight: '700',
color: '#1f2937',
marginBottom: 15,
textAlign: 'center',
},
usageText: {
fontSize: 16,
color: '#4b5563',
lineHeight: 24,
textAlign: 'center',
},
footer: {
paddingVertical: 15,
alignItems: 'center',
borderTopWidth: 1,
borderTopColor: '#e5e7eb',
backgroundColor: '#f9fafb',
},
footerText: {
fontSize: 14,
color: '#6b7280',
fontWeight: '500',
},
textInputContainer: {
flex: 1,
},
textInputInner: {
flexDirection: 'row',
alignItems: 'center',
},
textInputPlaceholder: {
height: 16,
backgroundColor: '#e5e7eb',
borderRadius: 2,
flex: 1,
},
textInputCursor: {
width: 2,
height: 16,
backgroundColor: '#3b82f6',
marginLeft: 2,
},
});
export default App;
这段React Native标签组件代码实现了一个高度可配置的标签系统,通过类型配置和尺寸配置来实现多样化的视觉效果。组件采用Pressable作为基础容器,支持触摸反馈和点击事件处理。类型配置系统通过getTypeStyle函数实现,针对不同的标签类型返回对应的颜色方案,包括主要、成功、警告、危险、信息和默认六种类型,每种类型都有对应的背景色、边框色和文字颜色。尺寸配置系统通过getSizeStyle函数实现,支持小、中、大三种尺寸,每种尺寸对应不同的字体大小、内边距和圆角半径。
在鸿蒙系统适配方面,这套实现方案面临着深层次的技术架构差异。React Native的标签组件依赖于基础组件的组合和样式系统,通过JavaScript对象配置视觉表现。而鸿蒙的ArkUI框架提供了Badge组件作为系统级的标签实现,采用声明式配置方式,开发者只需设置文本内容和样式参数,系统会自动处理标签的显示和布局。鸿蒙的Badge组件在底层直接调用系统的渲染服务,避免了跨语言通信带来的性能损耗。
鸿蒙的Badge组件内置了更丰富的样式选项,支持多种预设颜色主题和自定义样式配置。在交互处理方面,鸿蒙的组件直接在Native层处理触摸事件,响应更加灵敏流畅。React Native需要通过JavaScript桥接层传递事件,这在高频交互场景下容易出现延迟现象。

布局系统的差异也十分显著。React Native使用Flexbox布局配合样式对象控制组件外观,需要开发者手动计算各种元素的尺寸和位置关系。鸿蒙的Badge组件内置了智能的布局管理机制,能够自动处理标签的尺寸计算和位置排列,减少布局冲突的可能性。
资源管理机制上,React Native通过URI加载网络图标资源,而鸿蒙使用ResourceManager统一管理本地资源,这种差异影响了组件的加载性能和资源安全性。鸿蒙的资源管理机制提供了更好的缓存策略和访问控制。
动画系统的实现方式完全不同。React Native的动画在JavaScript线程计算后传递给原生组件,而鸿蒙的动画系统在Native层执行,能够实现更精确的时间控制和更高效的资源利用。特别是在处理标签的显示和隐藏动画时,鸿蒙的架构优势更加明显。
打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

最后运行效果图如下显示:
