例如,考虑下面的代码:
Rectangle {
id: idRectParent
Rectangle {
id: idRectChild1
component.onCompleted: {
console.log("Iam Child 1")
}
}
Rectangle {
id: idRectChild2
component.onCompleted: {
console.log("Iam Child 2")
}
}
component.onCompleted : {
console.log("Iam parent Rect")
}
}
如果我在
qmlscene
中运行它,我会得到下面的输出(我已经尝试了近 50 次)。
Iam parent Rect
Iam Child 2
Iam Child 1
为什么输出是上面的顺序,而不是:
Iam parent Rect
Iam Child 1
Iam Child 2
或
Iam Child 1
Iam Child 2
Iam parent Rect
或任何其他组合。
顺序未定义:
在对象实例化后发出。这可以用来 完整的 QML 环境完成后,在启动时执行脚本代码 成立。
对应的handler是onCompleted。有可能 在任何对象上声明。运行 onCompleted 处理程序的顺序 未定义。
https://doc.qt.io/qt-6/qml-qtqml-component.html#completed-signal
顺序是未定义的,但它是有意义的(并且可以凭经验观察),当为一项调用
OnCompleted
方法时,其所有子项都会被实例化并安全访问(并且属性已初始化),即使这些项目的 OnCompleted
事件孩子们还没有被叫到。
顺序由 C++ 类规定,对于简单声明,顺序从 Qt 4.8 到 5.15 保持不变。
该示例描述了一个包含项目的 QML 组件。 C++ 调用按以下顺序发生:
QQmlComponent::beginCreate()
被调用来创建组件。QQmlObjectCreator::createInstance()
来创建组件中的每个项目。QQmlObjectCreator::createInstance()
对于项目中声明的每个子项都会递归调用。QQmlObjectCreator::createInstance()
调用创建所有子级后,父级的 QQmlObjectCreator::createInstance()
继续执行,并将父级添加到 componentAttached 堆栈中以供稍后完成。QQmlComponent::beginCreate()
呼叫退出。QQmlComponent::completeCreate()
来完成组件。onCompleted
。这强制执行以下命令:
idRectParent
在 QQmlObjectCreator::createInstance()
中构造,子级在函数退出 QQmlObjectCreator::createInstance()
之前通过递归调用 idRectParent
开始构造。idRectChild1
完成 QQmlObjectCreator::createInstance()
并被推送到 componentAttached 堆栈上。idRectChild2
完成 QQmlObjectCreator::createInstance()
并被推送到 componentAttached 堆栈上。idRectParent
完成 QQmlObjectCreator::createInstance()
并被推送到 componentAttached 堆栈上。QQmlComponent::completeCreate()
调用 QQmlObjectCreator::finalize()
并且 componentAttached 堆栈被清空,并为每个项目发出 onCompleted
:
idRectParent
从 componentAttached 堆栈中弹出,并发出 onCompleted
信号。idRectChild2
从 componentAttached 堆栈中弹出,并发出 onCompleted
信号。idRectChild1
从 componentAttached 堆栈中弹出,并发出 onCompleted
信号。无论项目的层次结构有多深,都会维持此顺序:按照与声明相反的顺序先是父级,然后是子级。