In einer Ubuntu-Telefonanwendung muss ich eine Logik ausführen, wenn ein Ereignis eintritt. Da ich das QML nicht mit zu vielen Zeilen JavaScript belasten möchte, habe ich eine Klasse in einer externen Datei erstellt und das Signal mit einer ihrer Methoden verbunden:
Main.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)
}
}
}
}
Aktion.js
function Action() {
this.handleClick = function() {
console.log('handleClick');
this.process();
}
this.process = function() {
console.log('processing...')
}
}
Es funktioniert, aber ich kann aus dem Slot keine andere Methode aufrufen:
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
Warum wird „Prozess“ nicht als Funktion erkannt? Mache ich etwas falsch?
Antwort1
Ich glaube, das unmittelbare Problem besteht darin, dass sich der Kontext innerhalb der Funktionsdefinitionen ändert Action
. Das this
Objekt darin Action.handleClick()
ist Action.handleClick
, nicht Action
.
Aber gehen wir ein wenig zurück: Warum verwenden Sie hier das Paradigma „Funktion innerhalb einer Funktion“? Dies ist in Browser-Javascript üblich, da es in dieser Umgebung keine Namensräume gibt. Um zu vermeiden, dass andere Funktionen beeinträchtigt werden, täuschen Sie einen Namensraum vor, indem Sie ein Objekt erstellen, das alle Ihre Funktionen enthält.
AllerdingstutAction
Führen Sie Namensräume durch. Beachten Sie, dass Sie aus der QML-Datei referenzieren mussten ActionJS.Action
. Daher ist es nicht nötig, einen anderen Namensraum für Ihre Funktionen zu implementieren. Platzieren Sie sie einfach auf der obersten Ebene der JS-Datei:
function handleClick() {
console.log("handleClick");
process();
}
function process() {
console.log("processing...");
}
Führen Sie dann in Ihrer QML-Datei Folgendes aus:
Component.onCompleted: {
clickMeButton.clicked.connect(ActionJS.handleClick)
}
Oder nur
onClicked: ActionJS.handleClick()
Ich gehe hier davon aus, dass Sie eigentlich kein Action
Objekt für etwas anderes als Namespaces benötigen. Wenn doch, sollten Sie sich mitPrototyp. Vielleicht möchten Sie auch wissen über.pragma library
, wenn Sie diese JS-Datei in mehreren QML-Dateien verwenden möchten.