將訊號連接到 JavaScript 方法的正確方法是什麼?

將訊號連接到 JavaScript 方法的正確方法是什麼?

在 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

我認為最迫切的問題是 內部函數定義中的上下文發生了變化Actionthis裡面的物體是Action.handleClick()Action.handleClick不是Action

但讓我們回顧一下:為什麼在這裡使用函數內函數範例?這在瀏覽器 JavaScript 中很常見,因為該環境中沒有命名空間。為了避免破壞其他函數,您可以透過建立一個物件來保存所有函數來偽造命名空間。

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

相關內容