Wie verbindet man ein Signal richtig mit einer JavaScript-Methode?

Wie verbindet man ein Signal richtig mit einer JavaScript-Methode?

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 thisObjekt 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.

AllerdingstutActionFü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 ActionObjekt 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.

verwandte Informationen