qtqml-javascript-resources.html 10.3 KB
Newer Older
xuebingbing's avatar
xuebingbing committed
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- resources.qdoc -->
  <title>Defining JavaScript Resources in QML | Qt QML 5.11</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="../qtdoc/index.html">Qt 5.11</a></td><td ><a href="qtqml-index.html">Qt QML</a></td><td >Defining JavaScript Resources in QML</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right">Qt 5.11.2 Reference Documentation</td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#code-behind-implementation-resource">Code-Behind Implementation Resource</a></li>
<li class="level1"><a href="#shared-javascript-resources-libraries">Shared JavaScript Resources (Libraries)</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Defining JavaScript Resources in QML</h1>
<span class="subtitle"></span>
<!-- $$$qtqml-javascript-resources.html-description -->
<div class="descr"> <a name="details"></a>
<p>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 <code>JavaScript Resources</code> in QML).</p>
<p>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 <a href="qtqml-javascript-imports.html">imported</a> by other JavaScript resources, or included in <a href="qtqml-modules-topic.html">QML modules</a>.</p>
<a name="code-behind-implementation-resource"></a>
<h2 id="code-behind-implementation-resource">Code-Behind Implementation Resource</h2>
<p>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.</p>
<p>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 <code>.import</code> 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.</p>
<p>An example of a code-behind implementation resource follows:</p>
<pre class="cpp">

  <span class="comment">// MyButton.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  import <span class="string">&quot;my_button_impl.js&quot;</span> as Logic <span class="comment">// A new instance of this JavaScript resource</span>
                                      <span class="comment">// is loaded for each instance of Button.qml.</span>

  Rectangle {
      id: rect
      width: <span class="number">200</span>
      height: <span class="number">100</span>
      color: <span class="string">&quot;red&quot;</span>

      MouseArea {
          id: mousearea
          anchors<span class="operator">.</span>fill: parent
          onClicked: Logic<span class="operator">.</span>onClicked(rect)
      }
  }

</pre>
<pre class="cpp">

  <span class="comment">// my_button_impl.js</span>
  var clickCount <span class="operator">=</span> <span class="number">0</span>;   <span class="comment">// this state is separate for each instance of MyButton</span>
  function onClicked(button) {
      clickCount <span class="operator">+</span><span class="operator">=</span> <span class="number">1</span>;
      <span class="keyword">if</span> ((clickCount <span class="operator">%</span> <span class="number">5</span>) <span class="operator">=</span><span class="operator">=</span> <span class="number">0</span>) {
          button<span class="operator">.</span>color <span class="operator">=</span> <span class="type"><a href="qml-qtqml-qt.html">Qt</a></span><span class="operator">.</span>rgba(<span class="number">1</span><span class="operator">,</span><span class="number">0</span><span class="operator">,</span><span class="number">0</span><span class="operator">,</span><span class="number">1</span>);
      } <span class="keyword">else</span> {
          button<span class="operator">.</span>color <span class="operator">=</span> <span class="type"><a href="qml-qtqml-qt.html">Qt</a></span><span class="operator">.</span>rgba(<span class="number">0</span><span class="operator">,</span><span class="number">1</span><span class="operator">,</span><span class="number">0</span><span class="operator">,</span><span class="number">1</span>);
      }
  }

</pre>
<p>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.</p>
<a name="shared-javascript-resources-libraries"></a>
<h2 id="shared-javascript-resources-libraries">Shared JavaScript Resources (Libraries)</h2>
<p>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.</p>
<p><a href="qtqml-javascript-resources.html#code-behind-implementation-resource">The previous section</a> 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.</p>
<pre class="cpp">

  <span class="comment">// factorial.js</span>
  <span class="operator">.</span>pragma library

  var factorialCount <span class="operator">=</span> <span class="number">0</span>;

  function factorial(a) {
      a <span class="operator">=</span> parseInt(a);

      <span class="comment">// factorial recursion</span>
      <span class="keyword">if</span> (a <span class="operator">&gt;</span> <span class="number">0</span>)
          <span class="keyword">return</span> a <span class="operator">*</span> factorial(a <span class="operator">-</span> <span class="number">1</span>);

      <span class="comment">// shared state</span>
      factorialCount <span class="operator">+</span><span class="operator">=</span> <span class="number">1</span>;

      <span class="comment">// recursion base-case.</span>
      <span class="keyword">return</span> <span class="number">1</span>;
  }

  function factorialCallCount() {
      <span class="keyword">return</span> factorialCount;
  }

</pre>
<p>The pragma declaration must appear before any JavaScript code excluding comments.</p>
<p>Note that multiple QML documents can import <code>&quot;factorial.js&quot;</code> 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.</p>
<p>For example:</p>
<pre class="cpp">

  <span class="comment">// Calculator.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  import <span class="string">&quot;factorial.js&quot;</span> as FactorialCalculator <span class="comment">// This JavaScript resource is only</span>
                                               <span class="comment">// ever loaded once by the engine,</span>
                                               <span class="comment">// even if multiple instances of</span>
                                               <span class="comment">// Calculator.qml are created.</span>

  Text {
      width: <span class="number">500</span>
      height: <span class="number">100</span>
      property <span class="type">int</span> input: <span class="number">17</span>
      text: <span class="string">&quot;The factorial of &quot;</span> <span class="operator">+</span> input <span class="operator">+</span> <span class="string">&quot; is: &quot;</span> <span class="operator">+</span> FactorialCalculator<span class="operator">.</span>factorial(input)
  }

</pre>
<p>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.</p>
</div>
<!-- @@@qtqml-javascript-resources.html -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2018 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>