在 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做進行命名空間。請注意,您必須Action
從ActionJS.Action
QML 文件中進行引用。因此,不需要為您的函數實作另一個名稱空間;只需將它們放在 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 檔案。