写点什么

09 HarmonyOS NEXT 仿 uv-ui Tag 组件开发教程系列 (三)

作者:全栈若城
  • 2025-03-06
    北京
  • 本文字数:4380 字

    阅读完需:约 14 分钟

温馨提示:本篇博客的详细代码已发布到 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}
@Componentexport 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 渲染性能优化

@Componentstruct 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 拖拽排序

@Componentstruct 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 动画效果

@Componentstruct 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)    })})
复制代码
  1. 性能测试

  • 大数据量下的渲染性能

  • 频繁状态更新的响应速度

  • 内存占用情况

5. 常见问题解决

  1. 状态同步问题

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

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

总结

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

发布于: 刚刚阅读数: 7
用户头像

全栈若城

关注

解读Python与前端技术,助你成为技术大牛 2023-06-28 加入

我是一名专注于 Python 和前端技术的技术讲解者。我擅长将复杂的技术概念转化为简单易懂的语言,帮助初学者快速入门,并满足高级开发者对更深入理解的需求。

评论

发布
暂无评论
09 HarmonyOS NEXT 仿uv-ui Tag组件开发教程系列(三)_HarmonyOS NEXT_全栈若城_InfoQ写作社区