В приложении Ubuntu phone мне нужно выполнить некоторую логику, когда происходит событие. Поскольку я не хочу засорять QML слишком большим количеством строк JavaScript, я создал класс во внешнем файле и подключил сигнал к одному из его методов:
Основной.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
Почему 'process' не распознается как функция? Я что-то делаю не так?
решение1
Я считаю, что непосредственная проблема в том, что контекст изменяется внутри определений функций внутри Action
. this
Объект внутри Action.handleClick()
— это Action.handleClick
, а не Action
.
Но давайте вернемся немного назад: почему вы здесь используете парадигму «функция внутри функции»? Это распространено в браузерном Javascript, поскольку в этой среде нет пространства имен. Чтобы не затоптать другие функции, вы подделываете пространство имен, создавая объект для хранения всех ваших функций.
Однако, QMLделаетсделать namespaces. Обратите внимание, что вам пришлось ссылаться на Action
as ActionJS.Action
из файла QML. Поэтому нет необходимости реализовывать другое namespace для ваших функций; просто поместите их на верхний уровень файла 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
, если вы собираетесь использовать этот JS-файл в нескольких файлах QML.