Record

在鸿蒙(HarmonyOS)ArkTS开发中,Record 是一个工具类型,用于构造对象类型,其属性键为指定类型 Keys,属性值为指定类型 Type。它常用于将一种类型的属性映射到另一种类型,尤其适合处理键值对的集合场景。以下是具体说明和示例:

1. 基本语法

type RecordType = Record<Keys, Type>;
  • **Keys**:对象键的类型(通常是联合类型)。
  • **Type**:对象值的类型。

2. 使用示例

场景:学生成绩管理系统

// 定义课程联合类型
type Course = 'Math' | 'Chinese' | 'English';

// 定义成绩类型
type Grade = number;

// 使用Record定义学生成绩类型:键为课程,值为成绩
type StudentGrades = Record<Course, Grade>;

// 使用Record定义班级成绩类型:键为学号,值为学生成绩对象
type ClassGrades = Record<string, StudentGrades>;


// 学生成绩对象(符合StudentGrades类型)
let student1: StudentGrades = { Math: 90, Chinese: 85, English: 92 };
let student2: StudentGrades = { Math: 78, Chinese: 82, English: 85 };

// 班级成绩记录(符合ClassGrades类型)
const classGrades: ClassGrades = {
  '001': student1,
  '002': student2
};


@Entry
@Component
struct Index {
  // 根据学号计算平均分
  getAverageGrade(studentId: string, grades: ClassGrades): number | null {
    const studentGrades = grades[studentId];
    if (!studentGrades) {
      console.log(`Student with ID ${studentId} not found.`);
      return null;
    }

    // 获取课程数组并计算总分
    const courses = Object.keys(studentGrades) as Course[];
    const total = courses.reduce((sum, course) => sum + studentGrades[course], 0);
    return total / courses.length; // 返回平均分
  }

  build() {
    Column() {
      Button('计算平均分')
        .onClick(() => {
          // 输出:89
          console.log('学生平均分:', this.getAverageGrade('001', classGrades));
        })
    }
  }
}

3. 常用操作

遍历
let record: Record<string, number> = { "width": 666, "height": 888 };

// 先获取allkey,再遍历
const keys = Object.keys(record); // 返回 ['width', 'height']
for (let key of keys) {
  console.log(`Key: ${key}, Value: ${record[key]}`);
}
// 或写
keys.forEach(key => {
  console.log(`Key: ${key}, Value: ${record[key]}`);
});

// 直接获取allkey对其进行遍历
Object.keys(record).forEach(key => {
  console.log(`Key: ${key}, Value: ${record[key]}`);
});

4. 关键点说明

  • 类型安全Record 确保对象键和值的类型严格匹配,避免运行时错误。
  • 灵活性:支持嵌套使用(如 ClassGrades 中值类型为另一个 Record)。
  • 实用场景:适用于动态键名集合(如数据库查询结果、配置映射表)。

注意:若需处理音频录制等底层能力,请使用鸿蒙推荐的 AVRecorder 替代废弃的 AudioRecorder API(参考检索信息)。Record 类型仅用于类型定义,与多媒体录制无关。

string

charCodeAt(index: number): number方法

作用:返回指定位置字符的 Unicode 值。
@param index 所需字符的从零开始的索引。如果指定索引处没有字符,则返回 NaN。

split(separator: string | RegExp, limit?: number): string[];

作用:使用指定的分隔符将字符串分割成多个子字符串,并以数组形式返回。
separator: 分隔符,可以是字符串或正则表达式。需要注意的是,如果分隔符是正则表达式中的特殊字符(如点号.),你需要使用双反斜杠进行转义,例如应写为 split("\\.")而不是 split(".")。limit (可选): 一个数字,用于限制返回数组的最大长度。如果指定了该参数,则分割不会超过这个限制,返回的数组最多包含 limit 个元素。
关键特性与行为

了解 split() 方法的一些特定行为,有助于你更好地使用它:

  • 处理连续分隔符与空字符串:在鸿蒙Next中,split() 方法在遇到连续的分隔符时,其行为可能与某些其他编程语言或环境不同。它会忽略由此产生的空字符串。例如,分割 "a,,b" 会返回 ["a", "b"],而不是 ["a", "", "b"]

  • 无匹配分隔符的处理:如果字符串中没有找到指定的分隔符split() 方法会返回一个包含原字符串的数组 [原字符串]

  • 分隔符在开头或结尾:当分隔符出现在字符串开头或结尾时,同样需要注意产生的空字符串会被忽略。

代码示例

下面通过几个例子来展示 split() 方法在不同场景下的应用:

处理特殊字符分隔符

let filename: string = "main.page.ts";
let components: string[] = filename.split("\\."); // 注意:点号需要转义
console.log(components); // 输出: ["main", "page", "ts"] [citation:5]

注意,在鸿蒙Next中,对于点号这样的特殊字符,在split中需要使用双反斜杠转义。但实际ArkTS/TypeScript中,split方法的分隔符参数如果是字符串,通常不需要像正则表达式那样对点号进行转义。这一点建议你根据实际开发环境进行验证。

trim()、trimStart()、trimEnd()

在鸿蒙(HarmonyOS)应用开发中,如果你使用的是ArkTS语言,那么处理字符串首尾空白字符会非常方便,因为它直接使用了JavaScript/TypeScript的标准字符串方法。下面这个表格汇总了相关方法的核心用法:

方法名 作用 参数说明 返回值
trim() 去除字符串首尾所有空白字符  一个新的字符串,表示去除首尾空格后的结果
trimStart() 仅去除字符串开头(左侧)的空白字符  一个新的字符串,表示去除左侧空格后的结果
trimEnd() 仅去除字符串末尾(右侧)的空白字符  一个新的字符串,表示去除右侧空格后的结果

ResourceStr

在鸿蒙应用开发中,ResourceStr 和 string 是两种用于表示文本数据的类型,理解它们的区别对于编写正确且高效的代码非常重要。

为了帮你快速把握核心区别,可以参考下表:

对比维度 ResourceStr string
类型定义 联合类型:string | Resource TypeScript 基础字符串类型
本质 可以是字符串资源引用 普通的字符串字面量
适用场景 组件属性,需同时支持本地化资源引用和普通字符串 硬编码文本、网络数据、动态拼接字符串
灵活性 高,可接受两种类型值 低,仅接受字符串
多语言支持 支持,通过资源引用自动切换 不支持,内容固定

如何选择和使用

在实际编码中,你可以根据以下场景来决定使用哪种类型:

  • 使用 string 类型

    • 当文本内容是固定的,不需要随系统语言改变,例如某些内部标识、调试日志。

    • 当文本内容来自网络请求或用户动态输入

    // 固定字符串
    let fixedText: string = "这是一个静态文本";
    // 来自网络的字符串
    let networkData: string = await fetchDataFromNetwork();
  • 使用 ResourceStr 类型

    • 当组件的文本属性既可能显示本地化资源,又可能显示普通字符串时。例如,一个通用的按钮组件,可能显示资源文件中定义的"确认",也可能直接显示一个像"点击我"这样的普通字符串。

    // 使用资源引用
    let localizedText: ResourceStr = $r('app.string.submit_button');
    // 也可以直接使用字符串
    let plainText: ResourceStr = "直接显示的文本";
    
    // 在组件中使用
    Text(localizedText)
    Text(plainText)
  • 使用 Resource 类型

    • 当你明确需要引用 resources 目录下定义的资源时,例如通过 $r('app.string.hello') 或 $rawfile('filename') 方式引用的字符串、图片等。这确保了资源能被系统正确管理并支持多语言、深浅色模式等。

    // 专门用于资源引用
    let resourceOnly: Resource = $r('app.string.hello_world');
    Text(resourceOnly)

类型转换与比较

  • 类型转换:有时你可能会遇到需要将 Resource 类型转换为 string 的情况,例如在某些不支持 Resource 类型的组件或API中。这时可以使用资源管理器:

    typescript

    import common from '@ohos.app.ability.common';
    
    let context = getContext(this) as common.UIAbilityContext;
    // 将Resource转换为string
    let resourceString: Resource = $r('app.string.hello');
    let extractedString: string = context.resourceManager.getStringSync(resourceString.id);
    console.log(extractedString === "Hello"); // 比较字符串

    需要注意的是,直接使用 == 或 === 比较 Resource 对象和字符串通常不会得到预期的结果。建议先将 Resource 转换为 string 再比较,或者通过其他逻辑(如对比关联的变量)来判断。

  • 组件支持:大部分文本组件(如 Text)都支持 ResourceStr 类型。但一些特殊组件(如跑马灯、搜索框、富文本编辑器)可能仅支持 string 类型,这时就需要按上述方法进行转换。

数组

高阶函数

函数分类 核心函数 主要作用 鸿蒙开发中的典型应用场景
集合处理 map() 转换数组中的每个元素,并返回新数组。 将数据模型列表映射为对应的UI组件列表,例如将商品数组转换为ForEach中的商品卡片。
filter() 过滤数组,返回满足条件的新数组。 筛选数据,例如从所有消息中过滤出非空消息,或从列表中筛选出偶数。
reduce() 将数组元素累积计算为一个单一结果。 计算总和、平均值等。
forEach() 遍历数组,执行副作用操作,无返回值 简单遍历数组,例如打印日志。
find() / some() / every() 查询数组中满足条件的元素。 检查列表中是否存在(some)或所有元素都满足(every)某个条件。
const numbers = [1, 2, 3];
// 1. map: 转换元素
const squared = numbers.map(x => x * x); // [1, 4, 9]
// 2. filter: 筛选元素
const evens = numbers.filter(x => x % 2 === 0); // 
// 3. reduce: 累积计算
const sum = numbers.reduce((acc, cur) => acc + cur, 0); // 6
// 4. find()用来查找数组中满足条件的第一个元素
Let find = array.find(num => num === 2)
// 5. sort()用来实现数组排序
Let sort1 = array.sort((a,b) => a - b)//1,2,3,4,5 升序
Let sort2 = array.sort((a,b) => b - a)//5,4,3,2,1 降序


//链式调用举例
let numbers = [1, 2, 3, 4, 5];
let result = numbers
  .filter(it => it % 2 === 0) // 过滤出偶数 [2, 4]
  .map(it => it * it) // 计算平方 [4, 16]
  .reduce((sum, value) => sum + value, 0); // 求和 20
println(result);

常用函数

slice(start?: number, end?: number): T[];

下面表格总结了 slice 方法不同参数的情况:

调用方式 返回结果 说明
arr.slice(-1) 包含原数组最后1个元素的新数组 负数表示从数组末尾开始的偏移量
arr.slice(-2) 包含原数组最后2个元素的新数组 -
arr.slice(1, 4) 从索引1(包含)到索引4(不包含)的元素 左闭右开区间
arr.slice(0, -1) 从开始到倒数第二个元素的新数组 常用于复制并排除最后一个元素

汉字转拼音

在鸿蒙应用开发中,i18n.Transliterator.getInstance() 方法用于获取一个文本转写器,其主要功能之一就是实现汉字转拼音

转写模式 说明 示例(输入:"中国")
Any-Latn 将文本(如汉字)转换为带声调的拉丁字母(拼音) zhōng guó 
Latin-ASCII 带声调的拼音转换为不带声调的纯ASCII形式 zhong guo 

如何使用

  1. 导入模块:首先,确保在你的代码文件中导入国际化工具包。

    import { i18n } from '@kit.LocalizationKit';

  2. 转换实战:你可以直接使用单一模式,也可以组合两种模式,实现从汉字到无注音拼音的转换。

    // 1. 转换为带声调的拼音
    let transliteratorToTone = i18n.Transliterator.getInstance('Any-Latn');
    let pinyinWithTone = transliteratorToTone.transform('你好,世界!');
    console.info(`带声调拼音: ${pinyinWithTone}`); // 输出示例:nǐ hǎo, shì jiè!
    
    // 2. 转换为不带声调的拼音(组合使用)
    let transliteratorToTone2 = i18n.Transliterator.getInstance('Any-Latn');
    let transliteratorToPlain = i18n.Transliterator.getInstance('Latin-ASCII');
    let chineseText = "苹果";
    let intermediate = transliteratorToTone2.transform(chineseText); // 先转带声调拼音
    let finalPinyin = transliteratorToPlain.transform(intermediate); // 再去声调
    console.info(`不带声调拼音: ${finalPinyin}`); // 输出示例:ping guo

重要说明

  • 模式组合:鸿蒙的 Transliterator 目前主要提供上述两种与拼音相关的模式。如果需要得到不带声调的拼音,就需要像示例中那样,先将汉字转为带声调拼音,再使用 Latin-ASCII 模式去除声调。

  • 多音字处理:需要注意的是,这个接口对于多音字的处理可能无法保证100%准确。在开发对多音字要求苛刻的场景(如人名、地名处理)时,需要留意这一点。

  • 功能定位i18n.Transliterator 主要用于字符转写,如果需要进行精确的拼音转换(尤其是在商业级应用中),你可能需要评估是否能接受其精度。有更高要求时,可以考虑集成更专门的第三方拼音库。

ListScroller

基于鸿蒙(HarmonyOS)ArkTS开发规范,ListScroller是List组件的滚动控制器,用于精确控制列表滚动行为。List初始化时注入控制器:List({ scroller: this.listScroller })。核心功能如下:

核心方法 scrollToIndex()

listScroller.scrollToIndex(
  index: number, 
  smooth?: boolean, 
  align?: ScrollAlign
)
  • 参数说明
    • index:目标列表项的下标(从0开始)
    • smooth:是否启用平滑滚动(默认true
    • align:滚动对齐方式,可选值:
      • ScrollAlign.START:目标项对齐列表顶部
      • ScrollAlign.CENTER:目标项居中显示 ✅
      • ScrollAlign.END:目标项对齐列表底部

使用注意事项

当列表数据异步加载时,需确保数据加载完成后再执行滚动。

// 错误示例:数据未加载完成就滚动
this.listScroller.scrollToIndex(4);
this.productList.unshift('新增项'); // 数据变更导致下标偏移

// 正确方案:延迟二次滚动
this.listScroller.scrollToIndex(targetIndex);
setTimeout(() => {
  this.listScroller.scrollToIndex(targetIndex); // 500ms后重新校准
}, 500);

点击居中效果

@Component
struct CityList {
  private listScroller: ListScroller = new ListScroller()
  @State focusIndex: number = 0

  build() {
    List({ scroller: this.listScroller }) {
      ForEach(this.cityData, (item, index) => {
        ListItem() {
          Text(item.name)
            .onClick(() => {
              this.focusIndex = index;
              this.listScroller.scrollToIndex(index, true, ScrollAlign.CENTER); // 关键参数
            })
        }
      })
    }
  }
}

解决滚动位置错误

若遇滚动后位置偏移,需检查:

  1. 数据稳定性:滚动前是否触发数据变更(如unshift()/splice()
  2. 异步时序:网络加载完成前避免滚动操作
  3. 组件渲染:确保目标列表项已完成布局渲染

操作符

!== 和 != 

对比说明

在鸿蒙应用开发中,!== 和 != 都是用于比较的操作符,它们的核心区别在于比较时是否进行类型转换。为了让你能快速抓住要点,我先用一个表格来汇总它们的核心差异:

比较维度 !== (严格不相等) != (不相等)
类型检查 ✅ 严格:类型不同直接返回true ❌ 宽松:先尝试转换类型再比较
值比较 仅在类型相同时,比较值是否不同 类型转换后,比较值是否不同
推荐度 ⭐⭐⭐⭐⭐ 推荐使用,结果更精确 ⭐⭐ 可能产生预期外的结果
核心要点与最佳实践
  1. 优先使用 !==:在鸿蒙的ArkTS(声明式TypeScript)开发中,,应尽量使用 !== 进行比较,以避免因隐式类型转换导致的潜在错误。有一个比较常见的例外是,如果需要同时判断一个值是否为 null 或 undefined,可以使用 x == null,因为它等价于 x === null || x === undefined

  2. 理解比较逻辑!= 的比较逻辑是"先转换,再比较",而 !== 是"先看类型,类型不同就直接不相等,相同再比较值"。

  3. 注意特殊值:在处理 NaN 时需要特别小心,因为 NaN 与任何值(包括它自己)进行宽松相等(==)或严格相等(===)比较时,结果都是 false。如果需要判断一个值是否为 NaN,可以使用 isNaN() 函数。

=== 和 == 

对比说明

在鸿蒙应用开发中,=== 和 == 都是用于比较的操作符,它们的核心区别在于比较时是否进行类型转换。下面这个表格清晰地展示了它们的主要差异:

比较维度 === (严格相等) == (宽松相等)
类型检查 ✅ 严格:类型不同直接返回false ❌ 宽松:先尝试转换类型再比较
值比较 仅在类型相同时,比较值是否相等 类型转换后,比较值是否相等
性能 稍快(无需类型转换) 稍慢(需要类型转换)
推荐度 ⭐⭐⭐⭐⭐ 推荐使用 ⭐⭐ 谨慎使用
特殊情况说明
// NaN 的比较
console.log(NaN == NaN);    // false
console.log(NaN === NaN);   // false

// 使用 isNaN() 判断
console.log(isNaN(NaN));    // true

// 空字符串、0、false 的宽松比较
console.log("" == 0);       // true
console.log("" == false);   // true
console.log(0 == false);    // true

// 但严格比较都是 false
console.log("" === 0);      // false
console.log("" === false);  // false
console.log(0 === false);   // false
最佳实践建议
  1. 优先使用 ===:在鸿蒙的ArkTS开发中,强烈推荐使用 ===,因为:

    • 避免隐式类型转换导致的意外行为

    • 代码意图更明确

    • 更容易发现潜在的类型错误

  2. 谨慎使用 ==:只有在明确需要类型转换时才使用 ==,比如:

    // 从输入框获取的值(字符串)与数字比较
    let inputValue = "123";
    if (inputValue == 123) {
      // 这里会执行,因为"123" == 123
    }
  3. 处理 null 和 undefined时建议使用==

    // 检查是否为 null 或 undefined
    if (value == null) {
      // 等价于 value === null || value === undefined
    }
  4. 判断NaN时使用 isNaN() 判断
    console.log(isNaN(NaN));    // true

URL常用操作

encodeURI

在鸿蒙应用开发中,declare function encodeURI(uri: string): string;是一个用于处理完整URL编码的全局方法。为了帮你快速理解它的核心要点,我先用一个表格来汇总:

特性 描述
主要作用 整个统一资源标识符 进行编码
编码范围 处理空格等字符,但不编码协议头(http://)、域名部分以及/?=&:#等用于URL结构本身的保留字符
典型应用场景 当需要编码一个完整的URL字符串时使用
鸿蒙开发中的使用 可直接在ArkTS(基于TypeScript)的UI或逻辑代码中使用
与 encodeURIComponent 的区分

理解 encodeURI 和 encodeURIComponent 的区别至关重要,因为它们用于不同的场景:

  • encodeURI:适用于编码完整的URL。它会保留URL本身有特殊含义的功能字符(如:/?&=#),确保编码后的URL结构依然有效。

  • encodeURIComponent:适用于编码URL中的参数部分。它会编码几乎所有非标准字符,包括URL的功能字符。通常用于处理查询参数(即?后面的部分),防止参数中的特殊字符(如&=)破坏URL结构。

简单来说,encodeURI 照顾整个URL的完整性,而 encodeURIComponent 确保参数部分的安全性。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐