En una aplicación de teléfono Ubuntu, necesito realizar cierta lógica cuando ocurre un evento. Como no quiero contaminar el QML con demasiadas líneas de JavaScript, creé una clase en un archivo externo y conecté la señal a uno de sus 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)
}
}
}
}
acción.js
function Action() {
this.handleClick = function() {
console.log('handleClick');
this.process();
}
this.process = function() {
console.log('processing...')
}
}
Funciona, pero no puedo llamar a ningún otro método desde la ranura:
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 qué no se reconoce el "proceso" como una función? ¿Estoy haciendo algo mal?
Respuesta1
Creo que el problema inmediato es que el contexto cambia dentro de las definiciones de funciones internas Action
. El this
objeto del interior Action.handleClick()
lo es Action.handleClick
, no Action
.
Pero retrocedamos un poco: ¿por qué estás usando aquí el paradigma de función dentro de una función? Esto es común en el navegador Javascript, ya que no hay espacios de nombres en ese entorno. Para evitar pisotear otras funciones, falsificas un espacio de nombres creando un objeto que contenga todas tus funciones.
Sin embargo, QMLhacehacer espacios de nombres. Tenga en cuenta que tenía que hacer referencia Action
a ActionJS.Action
partir del archivo QML. Por lo tanto, no es necesario implementar otro espacio de nombres para sus funciones; simplemente colóquelos en el nivel superior del archivo JS:
function handleClick() {
console.log("handleClick");
process();
}
function process() {
console.log("processing...");
}
Luego en su archivo QML, haga
Component.onCompleted: {
clickMeButton.clicked.connect(ActionJS.handleClick)
}
O solo
onClicked: ActionJS.handleClick()
Supongo que en realidad no necesitas un Action
objeto para nada más que el espacio de nombres. Si lo haces, deberías aprender sobreprototipo. Quizás también quieras saber sobre.pragma library
, si tiene intención de utilizar este archivo JS en varios archivos QML.