ExtJS中实现第二个form.TextArea随第一个TextArea高度同步增长
问题背景
两个开启grow属性的Ext.form.TextArea组件,需要实现第一个文本域因内容输入自动增高时,第二个文本域高度同步跟随变化。
初始测试代码如下:
Ext.application({ name : 'Fiddle', launch : function() { Ext.create('Ext.form.TextArea', { renderTo: Ext.getBody(), width: 500, grow: true, id: 'm1', }); Ext.create('Ext.form.TextArea', { renderTo: Ext.getBody(), width: 500, grow: true, id: 'm2', }); }, });
已尝试的无效方案
- 直接给第二个文本域加bind配置绑定m1的height,未生效:
bind: { height: '{m1.height}', }
- 直接获取DOM元素设置高度,未生效:
var el = Ext.get("m1"); var e2 = Ext.get("m2"); e2.setHeight(e1.getHeight());
原因说明
- 直接用
Ext.create裸创建的组件没有挂载ViewModel上下文,bind配置根本找不到可解析的数据源,不可能生效;另外TextArea开了grow之后的高度调整是组件内部直接改输入框DOM高度,默认不会把高度变更同步成可绑定的响应式属性,就算有ViewModel也监听不到变化。 Ext.get()拿到的是DOM元素的包装对象,不是Ext组件实例,在DOM层面调setHeight不会触发组件的布局重算,设完很快就会被组件自身的布局逻辑覆盖,等于白设。
实现方案
方案1:resize事件监听(最简便,无需修改原有代码结构)
TextArea开启grow后,内容变化触发高度调整时会对外抛出resize事件,事件回调参数会返回组件最新的宽高,直接在回调里同步第二个组件的高度即可。
注意:被同步高度的第二个TextArea需要关闭grow属性,避免两个组件的自动增高逻辑冲突、循环触发高度调整。
完整代码:
Ext.application({ name: 'Fiddle', launch: function () { Ext.create('Ext.form.TextArea', { renderTo: Ext.getBody(), width: 500, grow: true, id: 'm1', listeners: { resize: function (sourceCmp, newWidth, newHeight) { const targetCmp = Ext.getCmp('m2'); targetCmp.setHeight(newHeight); } } }); Ext.create('Ext.form.TextArea', { renderTo: Ext.getBody(), width: 500, grow: false, // 必须关闭,避免高度逻辑冲突 id: 'm2' }); } });
方案2:正确配置bind实现(符合MVVM绑定规范)
如果一定要用bind的方式实现,需要先给组件挂载ViewModel,同时将源TextArea的高度变更同步到ViewModel的响应式数据中,绑定才能生效。
完整代码:
Ext.application({ name: 'Fiddle', launch: function () { Ext.create('Ext.container.Container', { renderTo: Ext.getBody(), viewModel: { data: { textareaHeight: 60 // TextArea默认初始高度 } }, items: [ { xtype: 'textarea', width: 500, grow: true, listeners: { resize: function (sourceCmp, newWidth, newHeight) { // 高度变化时同步更新ViewModel数据 sourceCmp.lookupViewModel().set('textareaHeight', newHeight); } } }, { xtype: 'textarea', width: 500, grow: false, bind: { height: '{textareaHeight}' } } ] }); } });
注意事项
- 获取Ext组件实例不要用
Ext.get(),该方法仅返回DOM包装对象;要获取组件实例请使用Ext.getCmp(组件id),或通过lookup()、组件查询方法获取,尽量减少全局id的使用避免命名冲突。 - 不要给两个TextArea同时开启
grow属性,否则会出现高度循环触发的问题:源组件增高→设置目标组件高度→目标组件自身grow逻辑触发再次变高→反向触发布局调整,最终高度异常。
内容的提问来源于stack exchange,提问作者Jakub
相关产品推荐
相关产品推荐

