(一): 组件概述与架构设计
效果演示
1. 组件简介
跑马灯(Marquee)组件是一个用于展示滚动文本的 UI 组件,主要用于处理文本内容超出显示区域时的展示问题。当文本内容过长时,组件会自动实现文本的循环滚动效果,并在每次循环结束后暂停一定时间。
2. 核心功能
文本自动滚动展示
支持自定义滚动速度和方向
可配置滚动间隔和动画效果
适配不同屏幕尺寸(手机/平板)
支持自定义文本样式
3. 基础架构
整个跑马灯组件由以下几个主要部分组成:
@Componentexport struct MarqueeViewComponent { // 主容器组件}@Componentstruct TripView { // 行程信息容器}@Componentstruct TripMessage { // 单条行程信息展示}@Componentexport struct FunctionDescription { // 功能描述组件}
复制代码
4. 关键类和接口
4.1 动画配置类
export class MarqueeAnimationModifier { iterations: number; // 动画播放次数 duration: number; // 动画持续时间 tempo: number; // 动画播放速度 playMode: PlayMode; // 播放模式 delayTime: number; // 延迟时间}
复制代码
4.2 滚动配置类
export class MarqueeScrollModifier { scrollWidth: Length; // 滚动区域宽度 space: number; // 文本间距}
复制代码
5. 组件层级结构
MarqueeViewComponent (根组件)├── FunctionDescription (功能描述)└── TripView (行程视图) └── TripMessage (行程信息) └── MarqueeSection (跑马灯核心组件)
复制代码
6. 使用场景
该组件特别适用于以下场景:
新闻公告滚动展示
长文本信息展示
消息通知展示
实时信息更新展示
7. 代码示例
基本使用方式:
MarqueeSection({ marqueeTextBuilder: () => { this.marqueeTextBuilder(this.tripDataItem.ticketEntrance) }, marqueeAnimationModifier: new MarqueeAnimationModifier(), marqueeScrollModifier: new MarqueeScrollModifier( display.isFoldable() ? $r('app.string.marquee_scroll_phone_width') : $r('app.string.marquee_scroll_tablet_width'), Constants.BLANK_SPACE )})
复制代码
8. 关键知识点解析
8.1 装饰器使用
@Component
: 声明一个自定义组件
@State
: 组件状态管理
@Builder
: 自定义构建函数
8.2 响应式设计
8.3 布局设计
9. 小结
跑马灯组件是一个功能完整、易于使用的 UI 组件,通过合理的架构设计和模块化的代码组织,使得组件具有良好的可维护性和扩展性。在后续的文章中,我们将深入探讨每个模块的具体实现细节。
(二): MarqueeSection 核心实现
效果演示
1. MarqueeSection 组件概述
MarqueeSection 是跑马灯组件的核心,负责实现文本的滚动效果。它通过配置动画参数和滚动属性,实现了流畅的文本滚动展示效果。
2. 核心配置类详解
2.1 MarqueeAnimationModifier 类
export class MarqueeAnimationModifier { iterations: number; // 动画循环次数 duration: number; // 持续时间(ms) tempo: number; // 播放速度 playMode: PlayMode; // 播放模式 delayTime: number; // 延迟时间(ms) constructor( iterations: number = -1, // 默认无限循环 duration: number = Constants.ANIMATION_DURATION, tempo: number = 1, // 默认速度 playMode: PlayMode = PlayMode.Reverse, // 默认反向播放 delayTime: number = Constants.DELAY_TIME // 默认延迟时间 ) { // 初始化配置 }}
复制代码
参数说明:
2.2 MarqueeScrollModifier 类
export class MarqueeScrollModifier { scrollWidth: Length; // 滚动区域宽度 space: number; // 文本间距 constructor( scrollWidth: Length = Constants.DEFAULT_SCROLL_WIDTH, space: number = Constants.BLANK_SPACE ) { this.scrollWidth = scrollWidth; this.space = space; }}
复制代码
参数说明:
3. 组件使用示例
3.1 基础使用方式
MarqueeSection({ // 定义文本内容构建器 marqueeTextBuilder: () => { this.marqueeTextBuilder(this.tripDataItem.ticketEntrance) }, // 配置动画属性 marqueeAnimationModifier: new MarqueeAnimationModifier(), // 配置滚动属性 marqueeScrollModifier: new MarqueeScrollModifier( display.isFoldable() ? $r('app.string.marquee_scroll_phone_width') : $r('app.string.marquee_scroll_tablet_width'), Constants.BLANK_SPACE )})
复制代码
3.2 自定义文本构建器
@BuildermarqueeTextBuilder(marqueeText: ResourceStr) { Text(marqueeText) .fontSize(16) .fontColor('#333333') // 可以添加更多文本样式}
复制代码
4. 适配处理
4.1 设备类型适配
display.isFoldable() ? $r('app.string.marquee_scroll_phone_width') : // 手机宽度 $r('app.string.marquee_scroll_tablet_width') // 平板宽度
复制代码
4.2 资源引用
// 在resources目录下定义不同设备的宽度// phone.json{ "marquee_scroll_phone_width": "300vp"}// tablet.json{ "marquee_scroll_tablet_width": "500vp"}
复制代码
5. 动画效果实现
5.1 动画流程
初始化:文本位于起始位置
延迟:等待 delayTime 时间
滚动:按照设定的速度和方向滚动
停顿:完成一次滚动后暂停
循环:重复以上步骤
5.2 关键参数配置
const Constants = { ANIMATION_DURATION: 8000, // 动画持续8秒 DELAY_TIME: 1000, // 延迟1秒 BLANK_SPACE: 100, // 文本间距100 DEFAULT_SCROLL_WIDTH: '300vp' // 默认滚动宽度}
复制代码
6. 性能优化
6.1 动态加载
使用 LazyForEach 实现数据的按需加载:
LazyForEach(this.tripData, (item: TripDataType) => { TripMessage({ tripDataItem: item })}, (item: TripDataType) => JSON.stringify(item))
复制代码
6.2 资源复用
通过 Builder 装饰器复用文本构建逻辑:
@BuildermarqueeTextBuilder(marqueeText: ResourceStr) { Text(marqueeText)}
复制代码
7. 常见问题解决
文本不滚动
检查 scrollWidth 是否合适
确认 iterations 不为 0
验证文本内容是否超出显示区域
滚动效果不流畅
调整 duration 值
优化 tempo 参数
检查设备性能状态
适配问题
使用响应式单位(vp)
根据设备类型设置不同参数
测试不同屏幕尺寸
8. 最佳实践
合理设置动画参数
注意性能优化
做好设备适配
保持代码简洁
遵循组件设计规范
通过以上详细讲解,相信你已经对 MarqueeSection 组件的实现原理和使用方法有了深入的了解。在实际开发中,可以根据具体需求调整相关参数,实现最佳的展示效果。
(三): 数据结构与状态管理
效果演示
1. 数据类型定义
1.1 行程数据类型
interface TripDataType { trainNumber: string; // 车次号 wholeCourse: string; // 全程 startingTime: string; // 出发时间 endingTime: string; // 到达时间 origin: string; // 始发站 destination: string; // 终点站 timeDifference: string; // 时间差 ticketEntrance: ResourceStr; // 票务入口 vehicleModel: string; // 车型}
复制代码
1.2 常量定义
const Constants = { ANGLE: 180, ANIMATION_DURATION: 8000, DELAY_TIME: 1000, BLANK_SPACE: 100, DEFAULT_SCROLL_WIDTH: '300vp'}
复制代码
2. 状态管理
2.1 组件状态声明
@Componentstruct TripView { // 使用@State装饰器管理数据源状态 @State tripData: TripDataSource = new TripDataSource();}
复制代码
2.2 状态更新机制
自动更新:
// 当tripData发生变化时,组件会自动重新渲染this.tripData = new TripDataSource();
复制代码
数据绑定:
LazyForEach(this.tripData, (item: TripDataType) => { TripMessage({ tripDataItem: item })})
复制代码
3. 数据源实现
3.1 TripDataSource 类
export class TripDataSource implements IDataSource { private tripList: TripDataType[] = []; // 实现IDataSource接口的必要方法 totalCount(): number { return this.tripList.length; } getData(index: number): TripDataType { return this.tripList[index]; }}
复制代码
3.2 数据加载和更新
class TripDataSource { // 初始化数据 constructor() { this.loadData(); } // 加载数据方法 private loadData() { // 可以从服务器或本地加载数据 this.tripList = [ { trainNumber: 'G1234', wholeCourse: '北京-上海', startingTime: '08:00', endingTime: '13:00', // ... 其他数据 } // ... 更多数据 ]; }}
复制代码
4. 属性传递
4.1 组件属性定义
@Componentstruct TripMessage { // 私有属性,用于接收父组件传递的数据 private tripDataItem: TripDataType = {} as TripDataType;}
复制代码
4.2 属性使用
TripMessage({ tripDataItem: item // 传递数据给子组件})
复制代码
5. 状态同步
5.1 父子组件通信
@Componentstruct ParentComponent { @State parentData: string = ''; build() { ChildComponent({ data: this.parentData, onDataChange: (newValue: string) => { this.parentData = newValue; } }) }}
复制代码
5.2 状态监听
@Componentstruct ChildComponent { @Prop data: string; onDataChange: (value: string) => void; build() { // 使用传入的数据和回调 }}
复制代码
6. 性能优化
6.1 懒加载实现
LazyForEach(this.tripData, (item: TripDataType) => { TripMessage({ tripDataItem: item })}, (item: TripDataType) => JSON.stringify(item))
复制代码
6.2 数据缓存
class TripDataSource { private cache: Map<string, TripDataType> = new Map(); getData(index: number): TripDataType { const key = `trip_${index}`; if (!this.cache.has(key)) { this.cache.set(key, this.tripList[index]); } return this.cache.get(key); }}
复制代码
7. 最佳实践
7.1 状态管理原则
最小化状态:只将必要的数据声明为状态
合理的状态粒度:避免过大或过小的状态
单一数据源:避免重复的状态声明
及时清理:不再需要的状态及时释放
7.2 数据处理建议
数据验证:
private validateTripData(data: TripDataType): boolean { return data && data.trainNumber && data.wholeCourse;}
复制代码
错误处理:
try { this.loadData();} catch (error) { console.error('Failed to load trip data:', error);}
复制代码
数据转换:
private formatTripData(raw: any): TripDataType { return { trainNumber: raw.trainNumber || '', wholeCourse: raw.wholeCourse || '', // ... 其他字段处理 };}
复制代码
8. 调试技巧
8.1 状态监控
@State@Watch('onTripDataChange')tripData: TripDataSource = new TripDataSource();onTripDataChange() { console.info('Trip data changed:', this.tripData);}
复制代码
8.2 性能分析
private measurePerformance() { const start = performance.now(); // 执行操作 const end = performance.now(); console.info('Operation took:', end - start, 'ms');}
复制代码
通过以上详细的讲解,你应该已经掌握了跑马灯组件中数据结构和状态管理的核心概念。这些知识将帮助你更好地理解和使用该组件,同时也能够在开发类似组件时应用这些最佳实践。
评论