当前位置: 首页 > news >正文

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

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


文章目录

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

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)
    })
})
  1. 性能测试
  • 大数据量下的渲染性能
  • 频繁状态更新的响应速度
  • 内存占用情况

5. 常见问题解决

  1. 状态同步问题
// 问题:子组件状态未同步到父组件
// 解决:使用双向绑定
@Component
struct ParentComponent {
    @State tags: TagItem[] = []

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

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

相关文章:

  • Linux rootfs:如何开机就自动添加某个用户?
  • 【C++】异常
  • 基于Canvas和和原生JS实现俄罗斯方块小游戏
  • torch.cat 函数介绍
  • 自然语言处理:Transformer、BERT
  • 数据结构(顺序表)
  • 基于PaddleNLP使用DeepSeek-R1搭建智能体
  • SpringBoot与Sentinel整合,解决DDoS攻击与异常爬虫请求问题
  • 系统思考与问题诊断
  • 【求100-200之间的素数】
  • 支持向量简要理解
  • AF3 squeeze_features函数解读
  • 高效运行 QwQ-32B + 错误修复
  • Ubuntu 下 Docker 企业级运维指南:核心命令与最佳实践深度解析20250309
  • AI Copilot——维新派的贾维斯,守旧派的墓志铭(程序员视角)
  • Synchronized 锁升级过程
  • 推荐一些免费开源支持Vue3甘特图组件
  • Python批量将中文文件名称转为英文、拼音的方法
  • 《基于深度学习的图像修复技术研究与应用-图像修复》—3000字论文模板
  • C++之“string”类的模拟实现
  • 六个最伤脊柱的姿势,你可能天天在做
  • 上海将完善隔代照料支持措施:建设老幼共享设施、提高科学育儿指导力度
  • 专访《风雪夜归人》导演闫锐:在舞台上表现什么是真正的活着
  • 受贿2.61亿余元,陕西省政协原主席韩勇一审被判死缓
  • 中美贸易代表会谈后是否已确定下一次会谈?外交部回应
  • 一周人物|收藏家瓦尔特捐出藏品,女性艺术家“对话”摄影