aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/doc/src/javascript/resources.qdoc
blob: d60101806a3b5e64b95ac2afc6caede34cb51ec5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtqml-javascript-resources.html
\title Defining JavaScript Resources in QML
\brief Description of how JavaScript files may be defined for use in QML

The program logic for a QML application may be defined in JavaScript.  The
JavaScript code may either be defined in-line in QML documents, or separated
into JavaScript files (known as \c {JavaScript Resources} in QML).

There are two different kinds of JavaScript resources which are supported in
QML: code-behind implementation files, and shared (library) files.  Both kinds
of JavaScript resource may be \l{qtqml-javascript-imports.html}{imported} by
other JavaScript resources, or included in \l{qtqml-modules-topic.html}
{QML modules}.

\section1 Code-Behind Implementation Resource

Most JavaScript files imported into a QML document are stateful implementations
for the QML document importing them.  In these cases, each instance of the QML
object type defined in the document requires a separate copy of the JavaScript
objects and state in order to behave correctly.

The default behavior when importing JavaScript files is to provide a unique,
isolated copy for each QML component instance.  If that JavaScript file does
not import any resources or modules with a \c{.import} statement, its code will
run in the same scope as the QML component instance and consequently can access
and manipulate the objects and properties declared in that QML component.
Otherwise, it will have its own unique scope, and objects and properties of the
QML component should be passed to the functions of the JavaScript file as
parameters if they are required.

An example of a code-behind implementation resource follows:

\code
// MyButton.qml
import QtQuick 2.0
import "my_button_impl.js" as Logic // A new instance of this JavaScript resource
                                    // is loaded for each instance of Button.qml.

Rectangle {
    id: rect
    width: 200
    height: 100
    color: "red"

    MouseArea {
        id: mousearea
        anchors.fill: parent
        onClicked: Logic.onClicked(rect)
    }
}
\endcode

\code
// my_button_impl.js
var clickCount = 0;   // this state is separate for each instance of MyButton
function onClicked(button) {
    clickCount += 1;
    if ((clickCount % 5) == 0) {
        button.color = Qt.rgba(1,0,0,1);
    } else {
        button.color = Qt.rgba(0,1,0,1);
    }
}
\endcode

In general, simple logic should be defined in-line in the QML file, but more
complex logic should be separated into code-behind implementation resources
for maintainability and readability.

\section1 Shared JavaScript Resources (Libraries)

By default, JavaScript files imported from QML share their context with the QML
component. That means the JavaScript files have access to the same QML objects
and can modify them. As a consequence, each import must have a unique copy of
these files.

\l {Defining JavaScript Resources in QML#Code-Behind Implementation Resource}
{The previous section} covers stateful imports of JavaScript files. However,
some JavaScript files are stateless and act more like reusable libraries, in
the sense that they provide a set of helper functions that do not require
anything from where they were imported from. You can save significant amounts
of memory and speed up the instantiation of QML components if you mark such
libraries with a special pragma, as shown in the following example.

\code
// factorial.js
.pragma library

var factorialCount = 0;

function factorial(a) {
    a = parseInt(a);

    // factorial recursion
    if (a > 0)
        return a * factorial(a - 1);

    // shared state
    factorialCount += 1;

    // recursion base-case.
    return 1;
}

function factorialCallCount() {
    return factorialCount;
}
\endcode

The pragma declaration must appear before any JavaScript code excluding comments.

Note that multiple QML documents can import \c{"factorial.js"} and call the
factorial and factorialCallCount functions that it provides.  The state of the
JavaScript import is shared across the QML documents which import it, and thus
the return value of the factorialCallCount function may be non-zero when called
within a QML document which never calls the factorial function.

For example:

\code
// Calculator.qml
import QtQuick 2.0
import "factorial.js" as FactorialCalculator // This JavaScript resource is only
                                             // ever loaded once by the engine,
                                             // even if multiple instances of
                                             // Calculator.qml are created.

Text {
    width: 500
    height: 100
    property int input: 17
    text: "The factorial of " + input + " is: " + FactorialCalculator.factorial(input)
}
\endcode

As they are shared, .pragma library files cannot access QML component instance
objects or properties directly, although QML values can be passed as function
parameters.

*/