StencilJS父传子key属性时@Prop()接收值为undefined问题排查
问题根因
key是Stencil(基于JSX虚拟DOM实现)的内置保留属性,框架在解析JSX时会单独提取该属性用于虚拟节点的diff计算、列表渲染时的节点复用判断,不会将其作为普通Prop传递给组件实例。因此无论你传入什么值,组件内部声明的@Prop() key始终会是undefined,和父组件传值是否有效、传入的是变量还是字面量没有关系。
修复方法
- 将业务层面需要传递的键值属性重命名,避开
key这个保留字,比如改成filterKey、columnKey等自定义名称,父子组件同步修改对应属性名即可正常传值。 - 列表循环时用于框架diff优化的
key属性可以正常保留,它只服务于框架层的渲染逻辑,和你业务传值不冲突。
修改后代码示例
父组件 smg-compound-filter.ts render 部分
render() { return ( <div class="smg-filter-container"> <div class="filters"> {this.filters.map(filter => { return ( <div class='filter'> <smg-filter key={filter.key} {/* 该属性供框架做diff使用,不会传入子组件Props */} filterKey={filter.key} {/* 重命名后的业务属性,可正常被子组件读取 */} label={filter.label} target={filter.target} options={filter.options} customClasses='secondary' onFilterChanged={(event) => this.toggleOption(event)} > </smg-filter> </div> ); })} </div> </div> ); }
子组件 smg-filter.ts 对应部分
export class SmgFilter { @State() filter: Filter; @State() showOptions: boolean; /** 自定义样式类 */ @Prop() customClasses: string; /** 关联的Smartsheet列字段 */ @Prop() filterKey: string; // 重命名Prop,避开key保留字 /** 筛选器标签 */ @Prop() label: string; /** 筛选项列表 */ @Prop() options: FilterOption[]; /** 筛选目标类型:'master' 或 'product' */ @Prop() target: FilterTarget; @Event() filterChanged: EventEmitter<Filter>; componentWillLoad() { console.log(this.filterKey); // 此处可正常获取传入的值 const isSecondary = this.customClasses?.includes('secondary'); this.showOptions = !isSecondary; this.filter = { key: this.filterKey, target: this.target, label: this.label, options: this.options, }; } }
注意事项
除key外,ref也是Stencil/JSX的内置保留属性,同样不能作为自定义Prop名使用,开发自定义属性时注意避开这类框架保留字段即可。
内容的提问来源于stack exchange,提问作者Achraf El Khamsi
相关产品推荐
相关产品推荐

