HarmonyOS鸿蒙Next中对于大量的设置选项怎么简化代码
HarmonyOS鸿蒙Next中对于大量的设置选项怎么简化代码 最近在写一个用于在鸿蒙系统上调试webview的软件,其中有一个设置界面,用于设置webview的行为
设置列表来源于属性-Web-ArkTS 组件-ArkWeb(方舟Web)-应用框架 - 华为HarmonyOS开发者
问题在于,我定义了一个响应式的对象Options,作为一个组件的属性(使用ComponentV2)
@Param @Require options: KWebOptions
现在的代码能够正常运行,但是过于繁琐,比如KWebOptions的定义:
@ObservedV2
export class KWebOptions {
@Trace javaScriptAccess: boolean;
// ... 44行
@Trace gestureFocusMode: GestureFocusMode;
constructor(options: Optional<KWebValue> = defaultInitValue) { // defaultInitValue用于存储默认值列表
this.javaScriptAccess = options.javaScriptAccess ?? defaultInitValue.javaScriptAccess
// ... 44行
this.gestureFocusMode = options.gestureFocusMode ?? defaultInitValue.gestureFocusMode
}
toRaw(){ // 为了JSON序列化保存配置
return {
javaScriptAccess: this.javaScriptAccess,
// ... 44行
gestureFocusMode: this.gestureFocusMode
}
}
}
我反复书写了总计44个属性3次。。。因为响应式对象似乎不能动态读取属性,不然我就一个for循环写完了
再比如,设置页面,一行设置的代码如下
ListItem() {
ItemToggle({
title: $r("app.string.web_options_java_script_access"),
value: this.options.javaScriptAccess,
onChange: (value: boolean) => this.options.javaScriptAccess = value
})
}.attributeModifier(this.itemStyle)
每一个设置我需要单独配置value和onChange两次,而且必须静态访问属性,意味着这个代码需要复制粘贴43次(虽然实际上我就是这么干的)
虽然但是,我觉得这玩意太折腾了,有没有能够优化的手段
更多关于HarmonyOS鸿蒙Next中对于大量的设置选项怎么简化代码的实战教程也可以访问 https://www.itying.com/category-93-b0.html
对于ItemToggle 可以配置一个对象属性参数,在这个对象里进行其他参数配置和方法实现。这里使用v1演示:
@Observed
class ToggleParams {
@Track title: string = ''
@Track value: boolean = false
onChange?: (v: boolean) => void
}
@Component
struct ItemToggle {
@ObjectLink params: ToggleParams
build() {
Text(this.params.title)
}
}
@Component
struct SettingsPage {
@State SETTING_CONFIGS: ToggleParams[] = []
aboutToAppear(): void {
const config: ToggleParams[] = []
for (let index = 0; index < 5; index++) {
const element = config[index];
//for循环创建
}
this.SETTING_CONFIGS = config
}
build() {
Column() {
List() {
ForEach(this.SETTING_CONFIGS, (item: ToggleParams) => {
ListItem() {
ItemToggle({
params: item
})
}.attributeModifier(this.itemStyle)
})
}
}
}
}
对于KWebOptions,可以使用一些model转类对象工具,比如class-transformer
ohpm i class-transformer
更多关于HarmonyOS鸿蒙Next中对于大量的设置选项怎么简化代码的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
一个很大的问题是这里的options是外面传进来的,外面有全局的状态保持和持久化,也是绑定到具体的Web组件对象上的,这里如果要手动定义SETTINGS数组,本质上还是需要把所有属性挨着展开写一遍没法用for循环,因为不支持动态属性
定义属性是必要的,方便类的内存布局。使用class-transformer可以不必再写
constructor(options: Optional<KWebValue> = defaultInitValue) 和 toRaw()。这样只写一遍属性定义。
const webOptionsInstance = plainToInstance(KWebOptions, options)
const rawObj = instanceToPlain(webOptionsInstance)
好哦,我试试
const SETTING_CONFIGS = [
{ key: 'javaScriptAccess', resId: 'app.string.web_options_java_script_access' },
{ key: 'gestureFocusMode', resId: 'app.string.web_options_gesture_focus' },
// ...其他配置项
];
@ComponentV2
struct SettingsPage {
@Param options: KWebOptions
build() {
Column() {
List() {
ForEach(SETTING_CONFIGS, item => {
ListItem() {
ItemToggle({
title: $r(item.resId),
value: this.options[item.key],
onChange: (v: boolean) => this.options[item.key] = v
})
}.attributeModifier(this.itemStyle)
})
}
}
}
}
不支持动态属性 this.options[item.key]报错 Indexed access is not supported for fields (arkts-no-props-by-index) <ArkTSCheck>,
鸿蒙Next中简化设置选项代码可使用@Builder装饰器封装UI组件,通过@State管理状态。利用ForEach循环渲染选项列表,结合@Link实现数据双向绑定。推荐使用Settings模块的预置组件(如Toggle、Slider)减少自定义控件代码。通过Preferences统一管理持久化数据,避免分散存储逻辑。
在HarmonyOS Next中处理大量设置选项时,可以通过以下方式简化代码:
1. 使用装饰器工厂和反射(需谨慎)
虽然ArkTS不支持运行时反射,但可以通过装饰器工厂模式减少重复。为@Trace装饰器创建工厂,自动生成属性的getter/setter,但需注意性能影响。
2. 配置化驱动UI生成 将属性配置抽取为数组,动态生成UI:
const optionConfigs = [
{ key: 'javaScriptAccess', title: $r("app.string.web_options_java_script_access"), type: 'boolean' },
// ... 其他配置
];
@Builder
function buildSettings(options: KWebOptions) {
ForEach(optionConfigs, (config) => {
ListItem() {
ItemToggle({
title: config.title,
value: options[config.key],
onChange: (value) => options[config.key] = value
})
}
})
}
3. 使用Proxy简化对象操作 通过Proxy代理实现属性的动态访问和序列化:
class KWebOptions {
private _data: Record<string, any> = {};
constructor(defaults: KWebValue) {
return new Proxy(this, {
get(target, prop) {
return target._data[prop] ?? defaults[prop];
},
set(target, prop, value) {
target._data[prop] = value;
return true;
}
});
}
toRaw() {
return { ...this._data };
}
}
4. 属性映射表 创建属性描述符映射表,统一管理初始化和序列化:
const propertyDescriptors = {
javaScriptAccess: { default: true, type: Boolean },
// ... 其他属性
};
class KWebOptions {
constructor(options?: Partial<KWebValue>) {
Object.entries(propertyDescriptors).forEach(([key, desc]) => {
Object.defineProperty(this, key, {
get() { /* ... */ },
set(value) { /* ... */ },
enumerable: true
});
});
}
}
5. 代码生成工具 对于44个属性这种情况,可以考虑使用简单的代码生成脚本(如Node.js脚本),根据属性列表自动生成类定义、构造函数和序列化方法。
推荐方案:采用配置化驱动UI生成结合Proxy模式,既能减少UI代码重复,又能简化对象操作。但需要注意Proxy在性能敏感场景下的使用,以及确保类型安全。

