英文:
Angular - change of property value ignored until output callback ends
问题
我有一个组件,应该在操作进行时显示一些加载符号:
html:
<spinner *ngIf='isLoading'></spinner>
<xx-table
(onSort)='onSort()'>
</xx-table>
Component.ts:
onSort(): void {
this.isLoading = true;
// 操作大约需要1秒
this.isLoading = false;
}
我有一行代码明确将this.isLoading
的值更改为true,但模板永远不会检测到这个更改。
似乎只有在onSort()
方法完成后才会触发变更检测 - 如果我删除this.isLoading = false;
这一行,加载符号会显示(并保持显示),但在约1秒后(操作的持续时间)才会消失。
如何在方法仍在执行时使此更改可见?这背后的确切机制是什么?
(我知道我可以手动触发变更检测,但为什么这不被识别为更改?)
英文:
I have component that should display some spinner while operation takes place:
html:
<spinner *ngIf='isLoading'></spinner>
<xx-table
(onSort)='onSort()'>
</xx-table>
Component.ts:
onSort(): void {
this.isLoading = true;
// operation lasting around 1 second
this.isLoading = false;
}
I have a line that explicitly changes value of this.isLoading
to true however this change is never detected by the template.
Seems like change detection is triggered only after onSort()
method is finished - if I remove line this.isLoading = false;
spinner is shown (and stays there) but after the ~1 second (duration of the operation that takes place)
How to make this change visible while method is still executing? And what exact mechanism is behind this?
(I know I can trigger change detection manually, but why this is not recognized as change?)
答案1
得分: 1
这个isLoading = false; 需要放在promise/observable的subscribe结束部分:在你的示例中,this.isLoading = true 直接跟在 = false 后面,因为你没有等待promise结束才进行这个赋值。
// 大约持续1秒的操作
是异步代码。查看如何在JavaScript中处理promise/Observable以理解这个概念。
英文:
this.isLoading = false;
needs to be at the end of the promise/observable subscribe: In your example, this.isLoading = true is directly followed by = false because you are not waiting for the end of the promise to do that assigment.
// operation lasting around 1 second
is asynch code. Look how to handle promise/Observable in JS to understand the concept.
答案2
得分: 1
A block of javascript code will continue executing until it completes, there is only one execution path. It looks like your code is synchronous and there are no async operations, so control is never returned to angular to update the page while isLoading
is true.
你的 JavaScript 代码块将一直执行,直到完成,只有一个执行路径。看起来你的代码是同步的,没有异步操作,因此在 isLoading
为 true 时,控制不会返回给 Angular 来更新页面。
You can use setTimeout
to schedule code to run after a certain number of milliseconds, or with '0' when the current execution path and pending events are handled by the JavaScript runtime:
你可以使用 setTimeout
来安排代码在一定毫秒数之后运行,或者使用 '0',这时当前的执行路径和未处理的事件将由 JavaScript 运行时处理:
doSomething(): void {
this.isLoading = true // never shows
this.expensiveOperation() // completes executing before updating UI
this.isLoading = false // when this function ends, isLoading is still false
}
doSomethingAsync(): void{
this.isLoading = true
setTimeout(() => { // let UI process changes, then do work
this.expensiveOperation()
this.isLoading = false
}, 0)
}
doSomething(): void {
this.isLoading = true // 永远不会显示
this.expensiveOperation() // 在更新 UI 之前完成执行
this.isLoading = false // 当此函数结束时,isLoading 仍然为 false
}
doSomethingAsync(): void{
this.isLoading = true
setTimeout(() => { // 让 UI 处理变化,然后执行工作
this.expensiveOperation()
this.isLoading = false
}, 0)
}
英文:
A block of javascript code will continue executing until it completes, there is only one execution path. It looks like your code is synchronous and there are no async operations, so control is never returned to angular to update the page while isLoading
is true.
You can use setTimeout
to schedule code to run after a certain number of milliseconds, or with '0' when the current execution path and pending events are handled by the javascript runtime:
doSomething(): void {
this.isLoading = true // never shows
this.expensiveOperation() // completes executing before updating UI
this.isLoading = false // when this function ends, isLoading is still false
}
doSomethingAsync(): void{
this.isLoading = true
setTimeout(() => { // let UI process changes, then do work
this.expensiveOperation()
this.isLoading = false
}, 0)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论