如何为代码生成元素绑定Knockout,或优化dxForm重绘时机?
问题
我在使用带数据绑定的DevExtreme dxForm组件时,给某个分组项添加了自定义模板,但formSettings.formData更新时,模板里的card内容不会同步更新——因为模板内元素未做数据绑定,手动添加data-bind属性也不生效。
我试过两种局部重绘表单的方法,均存在问题:
- 在表单不可见时执行重绘,jQuery找不到元素导致失败
- 在弹窗显示后执行,但需等待动画完成才触发,会显示约半秒的旧数据
相关代码
dxForm配置代码
formSettings: { formData: ko.observable(), scrollingEnabled: true, items: [{ itemType: 'group', name: 'LabelInfo', caption: 'Infos vom Label', template(data, itemElement) { const card = document.createElement('div'); card.classList.add('card'); itemElement.append(card); const cardBody = document.createElement('div'); cardBody.classList.add('card-body', 'lead'); card.append(cardBody); for (let i = 1; i <= 4; i++) { cardBody.append(document.createTextNode(data.formData[`line${i}`])); if (i < 4) cardBody.append(document.createElement('br')); } } }, // ... 其他表单项 ] }
尝试的重绘代码1
vm.lsl.formSettings.formData.subscribe(function () { // 刷新LabelInfo项 $('#lsl-form').dxForm('instance').itemOption('LabelInfo', 'visible', true); });
尝试的重绘代码2
vm.lsl.formSettings.formData(result.packagingInfo); $('#lsl-popup').dxPopup('instance').show().then(() => $('#lsl-form').dxForm('instance').itemOption('LabelInfo', 'visible', true));
解决方案
方法一:给自定义模板添加Knockout数据绑定
利用Knockout的响应式绑定实现模板内容自动更新,无需手动重绘:
template(data, itemElement) { const card = document.createElement('div'); card.classList.add('card'); itemElement.append(card); const cardBody = document.createElement('div'); cardBody.classList.add('card-body', 'lead'); card.append(cardBody); // 通过ko.computed监听formData变化,自动生成HTML内容 ko.applyBindingsToNode(cardBody, { html: ko.computed(() => { const formData = data.formData(); let htmlContent = ''; for (let i = 1; i <= 4; i++) { htmlContent += formData[`line${i}`] || ''; if (i < 4) htmlContent += '<br>'; } return htmlContent; }) }, data); }
说明:ko.computed会自动监听formData的变化,实时更新绑定的HTML内容,完全避免手动重绘的问题。
方法二:正确触发表单项重绘
若不想使用Knockout绑定,可调用dxForm专属API重绘指定项,并选对执行时机:
优化重绘逻辑
vm.lsl.formSettings.formData.subscribe(function () { const formInstance = $('#lsl-form').dxForm('instance'); if (formInstance) { // 直接重绘指定项,比修改visible属性更高效 formInstance.repaintItem('LabelInfo'); } });
配合弹窗的正确时机
监听弹窗的shown事件(弹窗完全显示、元素渲染完成后触发),避免动画等待导致的旧数据显示:
// 绑定弹窗shown事件 $('#lsl-popup').dxPopup('instance').on('shown', () => { const formInstance = $('#lsl-form').dxForm('instance'); if (formInstance) { formInstance.repaintItem('LabelInfo'); } }); // 设置数据并显示弹窗 vm.lsl.formSettings.formData(result.packagingInfo); $('#lsl-popup').dxPopup('instance').show();
说明:repaintItem是DevExtreme专为单个表单项提供的重绘API,比修改可见性更精准;shown事件确保表单元素已存在,不会出现找不到元素的问题。
内容的提问来源于stack exchange,提问作者André Reichelt
相关产品推荐
相关产品推荐

