Aurelia问题:repeat.for内自定义元素在集合变更后未创建
Aurelia新增模板后自定义元素不渲染的问题解决
我之前在Aurelia项目里也踩过完全一样的坑!你的问题根源其实很明确:新增的模板对象缺失了TemplateType属性,导致控制自定义元素渲染的if.bind条件不成立,所以编辑器组件没被创建;而列表能正常显示,是因为只用到了template.Key这个后端返回就存在的属性。
问题拆解
你初始化加载模板的时候,特意给每个对象手动加上了TemplateType标记:
data.forEach(function(obj) { obj.TemplateType = "email"; // 或者notification });
但调用createEmailTemplate/createNotificationTemplate返回的newTemplate,是直接从后端拿到的原始数据,并没有这个TemplateType属性。而你的自定义元素渲染完全依赖这个属性的判断:
<email-template-editor template.bind="template" if.bind="template.TemplateType == 'email'"></email-template-editor> <notification-template-editor template.bind="template" if.bind="template.TemplateType == 'notification'"></notification-template-editor>
条件不满足,自然不会渲染对应的编辑器组件。
快速修复方案
最直接的解决办法就是在新增模板时,手动给返回的对象补上TemplateType属性:
addMailTemplate() { this.dataAnalysisDefinitionService.createEmailTemplate(this.dad.Id).then(newTemplate => { // 给新邮件模板添加类型标记 newTemplate.TemplateType = "email"; this.templates.push(newTemplate); }); } addNotificationTemplate() { this.dataAnalysisDefinitionService.createNotificationTemplate(this.dad.Id).then(newTemplate => { // 给新通知模板添加类型标记 newTemplate.TemplateType = "notification"; this.templates.push(newTemplate); }); }
额外优化建议
- 简化初始化逻辑:你现在每次concat数组后都排序一次,可以合并成一次排序,代码更简洁高效:
activate() { const id = $("#data-analysis-definition-id").val(); const sortByCreatedAt = (a, b) => a.CreatedAt < b.CreatedAt ? -1 : a.CreatedAt > b.CreatedAt ? 1 : 0; return Promise.all([ this.dataAnalysisDefinitionService.get(id).then(data => { this.dad = data; }), this.dataAnalysisDefinitionService.getEmailTemplates(id).then(data => data.map(obj => ({ ...obj, TemplateType: "email" })) ), this.dataAnalysisDefinitionService.getNotificationTemplates(id).then(data => data.map(obj => ({ ...obj, TemplateType: "notification" })) ) ]).then(([_, emailTemplates, notificationTemplates]) => { this.templates = [...emailTemplates, ...notificationTemplates].sort(sortByCreatedAt); }); }
- 确保数组变更被Aurelia感知:虽然
push通常能被Aurelia的绑定系统检测到,但如果后端返回的是原生JSON对象(非可观测对象),偶尔会出现检测延迟的情况。如果遇到这种情况,可以用splice替代push:
// 替代push的写法,强制触发绑定更新 this.templates.splice(this.templates.length, 0, newTemplate);
不过这个属于兜底方案,上面的TemplateType属性补充才是核心修复。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

