• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# HML<a name="EN-US_TOPIC_0000001115974722"></a>
2
3-   [HML Page Structure](#en-us_topic_0000001059340504_section1062764791514)
4-   [Data Binding](#en-us_topic_0000001059340504_s8821c158917c48098219013e69129d1b)
5-   [Event Binding](#en-us_topic_0000001059340504_s30850b61328e4359910467ab33b3e07d)
6-   [Loop Rendering](#en-us_topic_0000001059340504_sb777d6d807fa43fea9be400b2600425b)
7-   [Conditional Rendering](#en-us_topic_0000001059340504_sf7f6eab2105a4030a1f34149417d6fc5)
8-   [Logic Control Block](#en-us_topic_0000001059340504_s185169def14340fcbb12c3375cb0f0bb)
9-   [Template Reference](#en-us_topic_0000001059340504_section1388145672114)
10
11The OpenHarmony Markup Language \(HML\) is an HTML-like language that allows you to build pages based on components and events. Pages built using HML have advanced capabilities such as  logic control, data binding, event binding, loop rendering, and conditional rendering.
12
13## HML Page Structure<a name="en-us_topic_0000001059340504_section1062764791514"></a>
14
15```
16<!-- xxx.hml -->
17<div class="item-container">
18  <text class="item-title">Image Show</text>
19  <div class="item-content">
20    <image src="/common/xxx.png" class="image"></image>
21  </div>
22</div>
23```
24
25## Data Binding<a name="en-us_topic_0000001059340504_s8821c158917c48098219013e69129d1b"></a>
26
27```
28<!-- xxx.hml -->
29<div onclick="changeText">
30  <text> {{content[1]}} </text>
31</div>
32```
33
34```
35// xxx.js
36export default {
37  data: {
38    content: ['Hello World!', 'Welcome to my world!']
39  },
40  changeText: function() {
41    this.content.splice(1, 1, this.content[0]);
42  }
43}
44```
45
46>![](public_sys-resources/icon-note.gif) **NOTE:**
47>-   To make the array data modification take effect, use the  **splice**  method to change array items.
48>-   ECMAScript 6.0 syntax is not supported in HML.
49
50## Event Binding<a name="en-us_topic_0000001059340504_s30850b61328e4359910467ab33b3e07d"></a>
51
52The callback bound to an event receives an event object parameter, which can be used to obtain the event information.
53
54```
55<!-- xxx.hml -->
56<div>
57  <!-- Bind an event using @. -->
58  <div @click="clickfunc"></div>
59  <!-- Bind an event using on. -->
60  <div onclick="clickfunc"></div>
61  <!-- Bind an event callback for event bubbling.5+ -->
62  <div on:touchstart.bubble="touchstartfunc"></div>
63 <!-- Bind the event callback for event capturing.5+ -->
64  <div on:touchstart.capture="touchstartfunc"></div>
65  <!-- on:{event} is equivalent to on:{event}.bubble.5+ -->
66  <div on:touchstart="touchstartfunc"></div>
67  <!-- Bind the event callback, but stop the event form bubbling upwards. 5+
68  <div grab:touchstart.bubble="touchstartfunc"></div>
69  <!-- Bind the event callback, but stop the event from being captured during downward transfer.5+ -->
70  <div grab:touchstart.capture="touchstartfunc"></div>
71  <!-- grab:{event} is equivalent to grab:{event}.bubble.5+ -->
72  <div grab:touchstart="touchstartfunc"></div>
73</div>
74```
75
76```
77// xxx.js
78export default {
79  data: {
80    obj: '',
81  },
82  clickfunc: function(e) {
83    this.obj = 'Hello World';
84    console.log(e);
85  },
86}
87```
88
89-   Example Code
90
91    ```
92    <!-- xxx.hml -->
93    <div class="container">
94      <text class="title">{{count}}</text>
95      <div class="box">
96        <input type="button" class="btn" value="increase" onclick="increase" />
97        <input type="button" class="btn" value="decrease" @click="decrease" />
98        <!-- Pass additional parameters. -->
99        <input type="button" class="btn" value="double" @click="multiply(2)" />
100        <input type="button" class="btn" value="decuple" @click="multiply(10)" />
101        <input type="button" class="btn" value="square" @click="multiply(count)" />
102      </div>
103    </div>
104    ```
105
106    ```
107    /* xxx.js */
108    export default {
109      data: {
110        count: 0
111      },
112      increase() {
113        this.count++;
114      },
115      decrease() {
116        this.count--;
117      },
118      multiply(multiplier) {
119        this.count = multiplier * this.count;
120      }
121    };
122    ```
123
124    ```
125    /* xxx.css */
126    .container {
127        display: flex;
128        flex-direction: column;
129        justify-content: center;
130        align-items: center;
131        left: 0px;
132        top: 0px;
133        width: 454px;
134        height: 454px;
135    }
136    .title {
137        font-size: 30px;
138        text-align: center;
139        width: 200px;
140        height: 100px;
141    }
142    .box {
143        width: 454px;
144        height: 200px;
145        justify-content: center;
146        align-items: center;
147        flex-wrap: wrap;
148    }
149    .btn {
150        width: 200px;
151        border-radius: 0;
152        margin-top: 10px;
153        margin-left: 10px;
154    }
155    ```
156
157
158## Loop Rendering<a name="en-us_topic_0000001059340504_sb777d6d807fa43fea9be400b2600425b"></a>
159
160```
161<!-- xxx.hml -->
162<div class="array-container">
163  <!-- div loop rendering -->
164  <!-- By default, $item indicates the element in the array, and $idx indicates the index of the element in the array. -->
165  <div for="{{array}}" tid="id" onclick="changeText">
166    <text>{{$idx}}.{{$item.name}}</text>
167  </div>
168  <!-- Define the name for an element variable. -->
169  <div for="{{value in array}}" tid="id" onclick="changeText">
170    <text>{{$idx}}.{{value.name}}</text>
171  </div>
172  <!-- Define an element variable and its index name. -->
173  <div for="{{(index, value) in array}}" tid="id" onclick="changeText">
174    <text>{{index}}.{{value.name}}</text>
175  </div>
176</div>
177```
178
179```
180// xxx.js
181export default {
182  data: {
183    array: [
184      {id: 1, name: 'jack', age: 18},
185      {id: 2, name: 'tony', age: 18},
186    ],
187  },
188  changeText: function() {
189    if (this.array[1].name === "tony"){
190      this.array.splice(1, 1, {id:2, name: 'Isabella', age: 18});
191    } else {
192      this.array.splice(2, 1, {id:3, name: 'Bary', age: 18});
193    }
194  },
195}
196```
197
198The  **tid**  attribute accelerates the  **for**  loop and improves the re-rendering efficiency when data in a loop changes.
199
200The  **tid**  attribute specifies the unique ID of each element in the array. If it is not specified, the index of each element in the array is used as the ID. For example,  **tid="id"**  indicates that the  **id**  attribute of each element is its unique ID.
201
202The  **for**  loop supports the following statements:
203
204-   for="array":  **array**  is an array object, whose element variable is  **$item**  by default.
205-   for="v in array":  **v**  is a custom element variable, whose index is  **$idx**  by default.
206-   for="\(i, v\) in array":  **i**  indicates the element index, and  **v**  indicates the element variable. All elements of the array object will be looped through.
207
208>![](public_sys-resources/icon-note.gif) **NOTE:**
209>-   Each element in the array must have the data attribute specified by  **tid**. Otherwise, an exception may occur.
210>-   The attribute specified by  **tid**  in the array must be unique. Otherwise, performance loss occurs. In the above example, only  **id**  and  **name**  can be used as  **tid**  because they are unique fields.
211>-   The  **tid**  field does not support expressions.
212
213## Conditional Rendering<a name="en-us_topic_0000001059340504_sf7f6eab2105a4030a1f34149417d6fc5"></a>
214
215There are two ways to implement conditional rendering:  **if-elif-else**  or  **show**. In  **if-elif-else**, when the  **if**  statement evaluates to  **false**, the component is not built in the VDOM and is not rendered. For  **show**, when show is  **false**, the component is not rendered but is built in the VDOM. In addition, the  **if-elif-else**  statements must be used in sibling nodes. Otherwise, the compilation fails. The following example uses both ways to implement conditional rendering:
216
217```
218<!-- xxx.hml -->
219<div class="container">
220  <button class="btn" type="capsule" value="toggleShow" onclick="toggleShow"></button>
221  <button class="btn" type="capsule" value="toggleDisplay" onclick="toggleDisplay"></button>
222  <text if="{{show}}"> Hello-One </text>
223  <text elif="{{display}}"> Hello-Two </text>
224  <text else> Hello-World </text>
225</div>
226```
227
228```
229// xxx.css
230.container{
231  flex-direction: column;
232  align-items: center;
233}
234.btn{
235  width: 280px;
236  font-size: 26px;
237  margin: 10px 0;
238}
239```
240
241```
242// xxx.js
243export default {
244  data: {
245    show: false,
246    display: true,
247  },
248  toggleShow: function() {
249    this.show = !this.show;
250  },
251  toggleDisplay: function() {
252    this.display = !this.display;
253  }
254}
255```
256
257In the optimized rendering \(**show**\), if  **show**  is  **true**, the node is rendered properly; if it is  **false**, the display style will be  **none**.
258
259```
260<!-- xxx.hml -->
261<div class="container">
262  <button class="btn" type="capsule" value="toggle" onclick="toggle"></button>
263  <text show="{{visible}}" > Hello World </text>
264</div>
265```
266
267```
268// xxx.css
269.container{
270  flex-direction: column;
271  align-items: center;
272}
273.btn{
274  width: 280px;
275  font-size: 26px;
276  margin: 10px 0;
277}
278```
279
280```
281// xxx.js
282export default {
283  data: {
284    visible: false,
285  },
286  toggle: function() {
287    this.visible = !this.visible;
288  },
289}
290```
291
292>![](public_sys-resources/icon-note.gif) **NOTE:**
293>Do not use  **for**  and  **if**  attributes at the same time in an element.
294
295## Logic Control Block<a name="en-us_topic_0000001059340504_s185169def14340fcbb12c3375cb0f0bb"></a>
296
297**<block\>**  makes loop rendering and conditional rendering more flexible. A  **<block\>**  will not be compiled as a real component. Note that the  **<block\>**  tag supports only the  **for**  and  **if**  attributes.
298
299```
300<!-- xxx.hml -->
301<list>
302  <block for="glasses">
303    <list-item type="glasses">
304      <text>{{$item.name}}</text>
305    </list-item>
306    <block for="$item.kinds">
307      <list-item type="kind">
308        <text>{{$item.color}}</text>
309      </list-item>
310    </block>
311  </block>
312</list>
313```
314
315```
316// xxx.js
317export default {
318  data: {
319    glasses: [
320      {name:'sunglasses', kinds:[{name:'XXX',color:'XXX'},{name:'XXX',color:'XXX'}]},
321      {name:'nearsightedness mirror', kinds:[{name:'XXX',color:'XXX'}]},
322    ],
323  },
324}
325```
326
327## Template Reference<a name="en-us_topic_0000001059340504_section1388145672114"></a>
328
329HML supports using elements to reference template files. For details, see  [Custom Components](basic-usage.md#EN-US_TOPIC_0000001162494627).
330
331```
332<!-- template.hml -->
333<div class="item">
334  <text>Name: {{name}}</text>
335  <text>Age: {{age}}</text>
336</div>
337```
338
339```
340<!-- index.hml -->
341<element name='comp' src='../../common/template.hml'></element>
342<div>
343  <comp name="Tony" age="18"></comp>
344</div>
345```
346
347