我有一个来自第三方的组件,该组件会发出“ onCellEdit”事件并传递一个cell元素作为参数。
在事件处理程序中,我想自动选择在此单元格内部生成的输入元素中的整个文本。
我遇到的问题是,当触发处理程序时,尚未加载输入元素。(cellElement as HTMLTableCellElement).querySelector('input')
不返回任何内容,因为我猜第三方组件需要一些时间。
我的解决方案现在看起来像这样:
selectTextOnEdit(cell: HTMLTableCellElement) {
const repeater = (element: HTMLTableCellElement) => {
const inputElement = element.querySelector('input');
if (inputElement) {
inputElement.select();
} else {
setTimeout(() => { repeater(element); }, 50);
}
};
repeater(cell);
}
然后,此功能触发转发器功能,该功能一直运行到找到输入元素为止。我知道我会丢失某种检查,以防输入元素永远不会生成..但这对这个问题并不重要。
我非常不喜欢这种解决方案,并且我肯定有更好的解决方案。
更新:
经过一些研究,我发现了有关“ MutationObserver”的信息。
这是我的新解决方案:
selectTextOnEdit(cell: HTMLTableCellElement) {
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.addedNodes && mutation.addedNodes.length > 0) {
const inputElement = cell.querySelector('input');
if (inputElement) {
inputElement.select();
observer.disconnect();
}
}
});
});
}
然而,如果从未创建输入元素,我不会如何断开与观察者的连接。
对于这种情况,我喜欢使用waitUntil
的实用程序功能。
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
...
export const waitUntil = async (untilTruthy: Function): Promise<boolean> => {
while (!untilTruthy()) {
await interval(25).pipe(
take(1),
).toPromise();
}
return Promise.resolve(true);
}
然后在您的函数中,它将是:
async selectTextOnEdit(cell: HTMLTableCellElement) {
await waitUntil(() => !!cell.querySelector('input'));
const inputElement = element.querySelector('input');
inputElement.select();
}
这是同一件事,但在我看来还是比较干净。为什么从来没有创建input
,如果调用selectTextOnEdit
的回调不应该总是创建它,这是一个问题吗?