Ext JS:Panel中tpl配置忽略html,如何同时使用两者?
解决ExtJS Panel子类同时使用tpl和bind html的问题
我来帮你搞定这个问题!在ExtJS里,tpl(模板)和绑定的html默认会互斥,因为当组件配置了tpl后,框架会优先用模板结合数据渲染内容,直接覆盖html的绑定结果。不过我们有几种方法可以实现两者同时生效:
方法1:将绑定的html整合到tpl中(最推荐)
把原来绑定的html内容作为模板的变量,通过bind给tpl传递数据,这样既能利用模板的格式化能力,又能保留数据绑定的特性。
修改后的代码示例:
Ext.define('InfoCard.Main', { extend: 'Ext.panel.Panel', viewModel: { type: 'infocardvm' }, layout: { type: 'table' }, items: [{ xtype: 'infocard', userCls: 'totalReCls', glyph: 'xf015@FontAwesome', // 定义包含绑定变量的模板,这里可以扩展任意模板内容 tpl: '<div class="custom-tpl-wrapper">{totalReBar}</div>', // 把ViewModel中的totalReBar绑定到模板需要的数据上 bind: { data: { totalReBar: '{totalReBar}' } } }] });
这种方式的好处是完全贴合ExtJS的设计逻辑,不需要自定义组件,代码更易维护。
方法2:自定义组件扩展updateHtml方法
如果你必须保留bind: {html: ...}的写法,同时要使用tpl,可以自定义infocard组件,重写updateHtml方法,让它在更新html时结合模板渲染内容。
首先扩展infocard组件:
Ext.define('InfoCard', { extend: 'Ext.panel.Panel', alias: 'widget.infocard', // 新增tpl配置项的默认值 tpl: null, // 重写updateHtml方法,结合模板渲染内容 updateHtml: function(newHtml) { if (this.tpl) { // 创建XTemplate实例,将html内容作为模板变量传入 const tpl = Ext.create('Ext.XTemplate', this.tpl); this.body.update(tpl.apply({ htmlContent: newHtml })); } else { // 没有tpl时,调用父类的默认逻辑 this.callParent(arguments); } }, // 新增setTpl方法,支持动态修改模板 setTpl: function(newTpl) { this.tpl = newTpl; // 如果已经有html内容,重新渲染 if (this.html) { this.updateHtml(this.html); } } });
然后在主组件中使用:
Ext.define('InfoCard.Main', { extend: 'Ext.panel.Panel', viewModel: { type: 'infocardvm' }, layout: { type: 'table' }, items: [{ xtype: 'infocard', userCls: 'totalReCls', bind: { html: '{totalReBar}' }, glyph: 'xf015@FontAwesome', // 模板中使用{htmlContent}来引用绑定的html内容 tpl: '<div class="total-re-bar">{htmlContent}</div>' }] });
这种方法适合需要保留原有html绑定逻辑的场景,灵活性更高。
方法3:嵌套组件分离tpl和html
如果你的tpl需要渲染更复杂的结构,可以用外层组件承载tpl,内层组件绑定html,通过布局把它们组合起来:
Ext.define('InfoCard.Main', { extend: 'Ext.panel.Panel', viewModel: { type: 'infocardvm' }, layout: { type: 'table' }, items: [{ xtype: 'infocard', userCls: 'totalReCls', glyph: 'xf015@FontAwesome', // 外层模板定义容器结构 tpl: '<div class="card-container"><div class="content-area"></div></div>', layout: 'fit', items: [{ // 内层组件绑定html内容,自动填充到外层模板的content-area中 xtype: 'component', bind: { html: '{totalReBar}' }, renderTo: function() { return this.up('infocard').body.down('.content-area'); } }] }] });
这种方式适合模板结构和html内容完全分离的场景,布局控制更精细。
内容的提问来源于stack exchange,提问作者Nuri Engin
相关产品推荐
相关产品推荐

