温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!

Tag组件实战应用与最佳实践

1. 复杂场景应用

1.1 标签筛选系统

// 多选标签组实现
import { Tag } from "../components/AutoTags"
interface tagGroupClass {
    groupId: string,
    title: string,
    tags: tagClass[]
}
interface tagClass {
    id: string,
    text: string,
    type: string
    groupId?: string
}

@Component
export struct FilterTags {
    @State selectedTags: Set<string> = new Set()
    @State tagGroups: tagGroupClass[] = [
        {
            groupId: 'g1',
            title: '类型',
            tags: [
                { id: '1', text: '重要', type: 'primary' },
                { id: '2', text: '普通', type: 'default' }
            ]
        },
        {
            groupId: 'g2',
            title: '状态',
            tags: [
                { id: '3', text: '进行中', type: 'warning' },
                { id: '4', text: '已完成', type: 'success' }
            ]
        }
    ]

    build() {
        Column({ space: 16 }) {
            ForEach(this.tagGroups, (group) => {
                Column({ space: 8 }) {
                    Text(group.title)
                        .fontSize(16)
                        .fontWeight(FontWeight.Medium)

                    Flex({ wrap: FlexWrap.Wrap }) {
                        ForEach(group.tags, (tag:tagClass) => {
                            Tag({
                                text: tag.text,
                                type: tag.type ?? 'default'
                            }).onClick(() => {
                                this.handleTagClick(tag.id)
                            })
                        })
                    }
                }
            })
        }
    }

    private handleTagClick(tagId: string) {
        if (this.selectedTags.has(tagId)) {
            this.selectedTags.delete(tagId)
        } else {
            this.selectedTags.add(tagId)
        }
        this.notifyFilterChange()
    }

    private notifyFilterChange() {
        // 处理筛选逻辑
        console.log(`筛选条件:${Array.from(this.selectedTags).join(',')}`)
    }
}

2. 性能优化实践

2.1 状态管理优化

// 优化前
@State private tags: Array<string> = []

// 优化后:使用Set提高查找效率
@State private tagSet: Set<string> = new Set()

// 优化数据结构
interface TagItem {
    id: string
    text: string
    type: string
    selected?: boolean
}

// 使用Map优化查找
@State private tagMap: Map<string, TagItem> = new Map()

2.2 渲染性能优化

@Component
struct OptimizedTags {
    // 使用@Builder抽取复用组件
    @Builder
    private TagItem(tag: TagItem) {
        Tag({
            text: tag.text,
            type: tag.type,
            closable: true
        })
        .margin(4)
    }

    // 使用懒加载优化大列表渲染
    build() {
        List({ space: 8 }) {
            LazyForEach(this.dataSource, (tag: TagItem) => {
                ListItem() {
                    this.TagItem(tag)
                }
            }, (tag: TagItem) => tag.id)
        }
    }
}

3. 实用功能扩展

3.1 拖拽排序

@Component
struct DraggableTags {
    @State tags: TagClass[] = []
    @State dragIndex: number = -1

    build() {
        Flex({ wrap: FlexWrap.Wrap }) {
            ForEach(this.tags, (tag, index) => {
                Tag({
                    text: tag.text,
                    type: tag.type
                })
                .gesture(
                    PanGesture()
                        .onActionStart(() => {
                            this.dragIndex = index
                        })
                        .onActionUpdate((event: GestureEvent) => {
                            // 处理拖拽逻辑
                        })
                        .onActionEnd(() => {
                            this.dragIndex = -1
                        })
                )
            })
        }
    }
}

3.2 动画效果

@Component
struct AnimatedTag {
    @State private isVisible: boolean = true
    @State private scale: number = 1

    build() {
        Tag({
            text: '动画标签',
            closable: true,
            onClose: () => {
                animateTo({
                    duration: 300,
                    curve: Curve.EaseInOut,
                    onFinish: () => {
                        this.isVisible = false
                    }
                }, () => {
                    this.scale = 0
                })
            }
        })
        .scale(this.scale)
        .opacity(this.isVisible ? 1 : 0)
    }
}

4. 最佳实践总结

4.1 代码组织

// 集中管理颜色配置
const TagColors = {
    text: {
        default: '#333333',
        primary: '#2468f2',
        // ...
    },
    background: {
        default: '#ffffff',
        primary: '#eef2ff',
        // ...
    },
    // ...
} as const

// 抽取通用逻辑
class TagUtils {
    static getColor(type: string, state: string): string {
        return Reflect.get(TagColors[state], type) || TagColors[state].default
    }

    static validateType(type: string): boolean {
        return ['default', 'primary', 'success', 'warning', 'danger'].includes(type)
    }
}

4.2 测试建议

  1. 单元测试

    // 测试颜色系统
    describe('TagUtils', () => {
     it('should return correct color', () => {
         expect(TagUtils.getColor('primary', 'text')).toBe('#2468f2')
         expect(TagUtils.getColor('invalid', 'text')).toBe('#333333')
     })
    
     it('should validate type correctly', () => {
         expect(TagUtils.validateType('primary')).toBe(true)
         expect(TagUtils.validateType('invalid')).toBe(false)
     })
    })
  2. 性能测试
  3. 大数据量下的渲染性能
  4. 频繁状态更新的响应速度
  5. 内存占用情况

5. 常见问题解决

  1. 状态同步问题

    // 问题:子组件状态未同步到父组件
    // 解决:使用双向绑定
    @Component
    struct ParentComponent {
     @State tags: TagItem[] = []
    
     build() {
         Column() {
             ChildTags({ tags: $tags })
         }
     }
    }
    
    @Component
    struct ChildTags {
     @Link tags: TagItem[]
     // ...
    }
  2. 性能问题

    // 问题:大量标签渲染卡顿
    // 解决:使用虚拟列表
    @Component
    struct VirtualTags {
     private virtualListController: VirtualListController = new VirtualListController()
    
     build() {
         VirtualList({ controller: this.virtualListController }) {
             ForEach(this.tags, (tag) => {
                 TagItem({ tag })
             })
         }
     }
    }

总结

在 HarmonyOS NEXT 仿uv-ui Tag组件开发教程系列中我们从零开始开发了Tag组件, 他的扩展性其实还是存在的, 当然在开发过程中需要注意的是,一定要注意性能优化的问题, 其次在案例源码中接口类型其实定义在当前的文件中 ,在正式开发的过程中建议创建一个 Types 文件夹 将定义的接口接口放在该文件夹下进行统一管理


全栈若城
1 声望1 粉丝