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

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 文件夹 将定义的接口接口放在该文件夹下进行统一管理


http://www.kler.cn/a/580630.html

相关文章:

  • React基础之项目创建
  • 在线json转ArkTs-Harmonyos
  • C 语言数据结构(二):顺序表和链表
  • 项目管理工具 Maven
  • docker学习使用教程
  • 航空发动机叶片检测-三维扫描技术重构精密制造质量体系
  • MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)
  • 游戏行业研究系列报告
  • k8s面试题总结(十二)
  • 在mac中设置环境变量
  • 【AIGC系列】6:HunyuanVideo视频生成模型部署和代码分析
  • STM32 CAN模块原理与应用详解
  • MySQL 数据库常用命令
  • postgreSQL window function高级用法
  • Facebook 隐私保护技术的发展与未来趋势
  • 探索在生成扩散模型中基于RAG增强生成的实现与未来
  • 初次体验Tauri和Sycamore(3)通道实现
  • 自然语言处理:无监督朴素贝叶斯模型
  • <3D建模>.max文件转换为.fbx文件
  • Ubuntu 24.04.2 允许 root 登录桌面、 ssh 远程、允许 Ubuntu 客户机与主机拖拽传递文件