在 Ubuntu 手机应用程序中,我需要在事件发生时执行一些逻辑。由于我不想用太多行 JavaScript 污染 QML,因此我在外部文件中创建了一个类,并将信号连接到其方法之一:
主文件.qml
import QtQuick 2.0
import Ubuntu.Components 1.1
import "action.js" as ActionJs
MainView {
objectName: "mainView"
applicationName: "example.cos64"
useDeprecatedToolbar: false
width: units.gu(20)
height: units.gu(20)
Page {
Button {
id: clickMeButton
text: "Click me"
onClicked: {
console.log('clicked');
}
Component.onCompleted: {
var action = new ActionJs.Action();
clickMeButton.clicked.connect(action.handleClick)
}
}
}
}
动作.js
function Action() {
this.handleClick = function() {
console.log('handleClick');
this.process();
}
this.process = function() {
console.log('processing...')
}
}
它可以工作,但我无法从插槽中调用任何其他方法:
Starting /usr/lib/x86_64-linux-gnu/qt5/bin/qmlscene...
qml: clicked
qml: handleClick
file:///home/co64/projects/ubuntu/Example/action.js:5: TypeError: Property 'process' of object [object Object] is not a function
为什么“进程”未被识别为函数?我做错了什么吗?
答案1
我认为直接的问题是函数定义内部的上下文发生了变化Action
。this
里面的对象Action.handleClick()
是Action.handleClick
,不是Action
。
但是让我们稍微回顾一下:为什么在这里使用函数内函数范式?这在浏览器 Javascript 中很常见,因为该环境中没有命名空间。为了避免破坏其他函数,您可以通过创建一个对象来保存所有函数来伪造命名空间。
然而,QML做进行命名空间。请注意,您必须从 QML 文件中引用Action
。ActionJS.Action
因此,无需为您的函数实现另一个命名空间;只需将它们放在 JS 文件的顶层:
function handleClick() {
console.log("handleClick");
process();
}
function process() {
console.log("processing...");
}
然后在你的 QML 文件中,执行
Component.onCompleted: {
clickMeButton.clicked.connect(ActionJS.handleClick)
}
要不就
onClicked: ActionJS.handleClick()
我在这里假设你实际上不需要Action
对象来做除命名空间之外的事情。如果你需要,你应该了解原型. 您可能还想了解.pragma library
,如果您打算在多个 QML 文件中使用此 JS 文件。