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

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

文章目录

    • Tag组件实战应用与最佳实践
      • [1. 复杂场景应用](#1. 复杂场景应用)
        • [1.1 标签筛选系统](#1.1 标签筛选系统)
      • [2. 性能优化实践](#2. 性能优化实践)
        • [2.1 状态管理优化](#2.1 状态管理优化)
        • [2.2 渲染性能优化](#2.2 渲染性能优化)
      • [3. 实用功能扩展](#3. 实用功能扩展)
        • [3.1 拖拽排序](#3.1 拖拽排序)
        • [3.2 动画效果](#3.2 动画效果)
      • [4. 最佳实践总结](#4. 最佳实践总结)
        • [4.1 代码组织](#4.1 代码组织)
        • [4.2 测试建议](#4.2 测试建议)
      • [5. 常见问题解决](#5. 常见问题解决)
    • 总结

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

1. 复杂场景应用

1.1 标签筛选系统
typescript 复制代码
// 多选标签组实现
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 状态管理优化
typescript 复制代码
// 优化前
@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 渲染性能优化
typescript 复制代码
@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 拖拽排序
typescript 复制代码
@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 动画效果
typescript 复制代码
@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 代码组织
typescript 复制代码
// 集中管理颜色配置
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. 单元测试
typescript 复制代码
// 测试颜色系统
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. 状态同步问题
typescript 复制代码
// 问题:子组件状态未同步到父组件
// 解决:使用双向绑定
@Component
struct ParentComponent {
    @State tags: TagItem[] = []

    build() {
        Column() {
            ChildTags({ tags: $tags })
        }
    }
}

@Component
struct ChildTags {
    @Link tags: TagItem[]
    // ...
}
  1. 性能问题
typescript 复制代码
// 问题:大量标签渲染卡顿
// 解决:使用虚拟列表
@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 文件夹 将定义的接口接口放在该文件夹下进行统一管理

相关推荐
爱笑的眼睛113 天前
HarmonyOS Next 弹窗系列教程(5)
华为·harmonyos·harmonyos next
HarmonyOS小助手4 天前
【鸿蒙生态学堂04】ArkUI开发基础(上)
harmonyos·鸿蒙·harmonyos next·arkui(方舟ui框架)介绍·使用常用组件构建页面·harmonyos 5.0·鸿蒙5·鸿蒙课程·鸿蒙生态
枫叶丹44 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(三十)
华为·harmonyos·deveco studio·harmonyos next
IUings5 天前
【鸿蒙】HarmonyOS NEXT之如何正常加载地图组件
开发语言·华为·harmonyos·harmonyos next·地图服务·map kit
枫叶丹410 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十八) -> 开发云对象
华为·harmonyos·deveco studio·harmonyos next
枫叶丹412 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十七) -> 开发云函数
华为·harmonyos·deveco studio·harmonyos next
HarmonyOS小助手13 天前
鸿蒙版微信小程序不可用,一文告诉你10分钟修复
harmonyos·鸿蒙·harmonyos next
枫叶丹415 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十六) -> 创建端云一体化开发工程
华为·harmonyos·deveco studio·harmonyos next
枫叶丹418 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十五) -> 端云一体化开发 -> 业务介绍(二)
华为·harmonyos·deveco studio·harmonyos next