Qual é a maneira correta de conectar um sinal a um método JavaScript?

Qual é a maneira correta de conectar um sinal a um método JavaScript?

Em um aplicativo de telefone Ubuntu, preciso executar alguma lógica quando ocorre um evento. Como não quero poluir o QML com muitas linhas de JavaScript, criei uma classe em um arquivo externo e conectei o sinal a um de seus métodos:

Principal.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)
            }
        }
    }
}

ação.js

function Action() {

    this.handleClick = function() {
        console.log('handleClick');
        this.process();
    }

    this.process = function() {
        console.log('processing...')
    }
}

Funciona, mas não consigo chamar nenhum outro método do slot:

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

Por que o 'processo' não é reconhecido como uma função? Estou fazendo algo errado?

Responder1

Acredito que o problema imediato é que o contexto muda dentro das definições de função dentro de Action. O thisobjeto dentro Action.handleClick()é Action.handleClick, não Action.

Mas vamos voltar um pouco: por que você está usando o paradigma função dentro de uma função aqui? Isso é comum no Javascript do navegador, já que não há namespace nesse ambiente. Para evitar atropelar outras funções, você falsifica um namespace criando um objeto para armazenar todas as suas funções.

No entanto, QMLfazfaça namespace. Observe que você teve que fazer referência Actiona ActionJS.Actionpartir do arquivo QML. Portanto, não há necessidade de implementar outro namespace para suas funções; basta colocá-los no nível superior do arquivo JS:

function handleClick() {
    console.log("handleClick");
    process();
}

function process() {
    console.log("processing...");
}

Então, no seu arquivo QML, faça

Component.onCompleted: {
    clickMeButton.clicked.connect(ActionJS.handleClick)
}

Ou apenas

onClicked: ActionJS.handleClick()

Estou assumindo aqui que você realmente não precisa de um Actionobjeto para nada além de namespace. Se você fizer isso, você deve aprender sobreprotótipo. Você também pode querer saber sobre.pragma library, se você pretende usar esse arquivo JS em vários arquivos QML.

informação relacionada