将信号连接到 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进行命名空间。请注意,您必须从 QML 文件中引用ActionActionJS.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 文件。

相关内容