Angular中如何通过字符串路径动态绑定嵌套对象属性
问题原因
原生JavaScript的方括号属性访问语法只会把传入的字符串识别为单个属性名,不会自动按.拆分解析嵌套路径,所以d1["p1.id"]实际查找的是d1上键名完全等于p1.id的属性,自然拿不到d1.p1.id的值。
你之前用的临时方案只是做了一次初始值拷贝,后续输入框修改的是你手动添加的同名字段,不会同步到原嵌套属性上,双向绑定实际是失效的。
可行解决方案
在可复用组件内实现嵌套路径的自定义取值、赋值逻辑,将[(ngModel)]的双向绑定拆分为属性绑定、事件更新两部分,绕过原生方括号访问的限制即可。
第一步:改造可复用组件的TS逻辑
新增嵌套路径解析、读写的工具方法,通过getter读取对应路径的值,通过值变更回调写回原对象对应属性:
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; @Component({ selector: "app-reusable[data][nestedProperty]", templateUrl: "./reusable.component.html" }) export class ReusableComponent<T> { @Input() nestedProperty!: string @Input() data!: T // 缓存拆分后的路径数组,避免重复计算 private propPath: string[] = []; ngOnChanges(changes: SimpleChanges): void { if (changes['nestedProperty']?.currentValue) { this.propPath = this.nestedProperty.split('.'); } } // 读取嵌套路径对应的值 get fieldValue(): any { return this.propPath.reduce((current, key) => { return current == null ? undefined : current[key]; }, this.data); } // 值变更时写回原对象的对应嵌套属性 onFieldValueChange(newValue: any): void { if (this.propPath.length === 0) return; const pathCopy = [...this.propPath]; const lastKey = pathCopy.pop()!; const target = pathCopy.reduce((current, key) => { return current == null ? undefined : current[key]; }, this.data); if (target) { target[lastKey] = newValue; } } }
第二步:修改可复用组件模板
不要直接用[(ngModel)]绑定单级属性,改为绑定自定义的读写逻辑:
<input [ngModel]="fieldValue" (ngModelChange)="onFieldValueChange($event)">
方案说明
- 根组件不需要做任何额外改造,不需要手动给实例添加路径同名属性,直接传入数据对象和点分隔的嵌套路径字符串即可正常工作
- 所有读写操作都是直接操作原传入的data对象,没有值拷贝,修改输入框内容会直接同步到对应嵌套属性上,实现真正的双向绑定
- 这套逻辑天然兼容数组索引路径,比如传入
list.0.name这类路径也能正常解析,不需要额外修改 - 不要用
eval实现路径解析,存在明确的XSS安全风险,逐层遍历访问的方式性能和安全性都有保障 - 如果业务中存在属性名本身包含
.的极端场景,可以自定义路径分隔符替换默认的.拆分逻辑即可适配。
内容的提问来源于stack exchange,提问作者Sulejman
相关产品推荐
相关产品推荐

