1e41f4b71Sopenharmony_ci# HML
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciHML 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 data binding, event binding, loop rendering, and conditional rendering.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci## HML Page Structure
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci```html
11e41f4b71Sopenharmony_ci<!-- xxx.hml -->
12e41f4b71Sopenharmony_ci<div class="item-container">
13e41f4b71Sopenharmony_ci  <text class="item-title">Image Show</text>
14e41f4b71Sopenharmony_ci  <div class="item-content">
15e41f4b71Sopenharmony_ci    <image src="/common/xxx.png" class="image"></image>
16e41f4b71Sopenharmony_ci  </div>
17e41f4b71Sopenharmony_ci</div>
18e41f4b71Sopenharmony_ci```
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci## Data Binding
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci```html
25e41f4b71Sopenharmony_ci<!-- xxx.hml -->
26e41f4b71Sopenharmony_ci<div onclick="changeText">
27e41f4b71Sopenharmony_ci  <text> {{content[1]}} </text>
28e41f4b71Sopenharmony_ci</div>
29e41f4b71Sopenharmony_ci```
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci```js
33e41f4b71Sopenharmony_ci// xxx.js
34e41f4b71Sopenharmony_ciexport default {
35e41f4b71Sopenharmony_ci  data: {
36e41f4b71Sopenharmony_ci    content: ['Hello World!', 'Welcome to my world!']
37e41f4b71Sopenharmony_ci  },
38e41f4b71Sopenharmony_ci  changeText: function() {
39e41f4b71Sopenharmony_ci    this.content.splice(1, 1, this.content[0]);
40e41f4b71Sopenharmony_ci  }
41e41f4b71Sopenharmony_ci}
42e41f4b71Sopenharmony_ci```
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci>  **NOTE**
45e41f4b71Sopenharmony_ci>  - To make the array data modification take effect, use the **splice** method to change array items.
46e41f4b71Sopenharmony_ci>
47e41f4b71Sopenharmony_ci>  - ECMAScript 6.0 syntax is not supported in HML.
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci## Event Binding
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ciThe callback bound to an event receives an event object parameter, which can be used to obtain the event information.
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci```html
56e41f4b71Sopenharmony_ci<!-- xxx.hml -->
57e41f4b71Sopenharmony_ci<div>
58e41f4b71Sopenharmony_ci  <!-- Bind an event using @. -->
59e41f4b71Sopenharmony_ci  <div @click="clickfunc"></div>
60e41f4b71Sopenharmony_ci  <!-- Bind an event using on. -->
61e41f4b71Sopenharmony_ci  <div onclick="clickfunc"></div>
62e41f4b71Sopenharmony_ci  <!--  Bind an event using on.<sup>5+</sup> This statement is not recommended. -->
63e41f4b71Sopenharmony_ci  <div onclick="clickfunc"></div>
64e41f4b71Sopenharmony_ci  <!-- Bind an event callback for event bubbling.<sup>5+</sup>-->
65e41f4b71Sopenharmony_ci  <div on:click.bubble="clickfunc"></div>
66e41f4b71Sopenharmony_ci  <!-- on:{event} is equivalent to on:{event}.bubble.<sup>5+</sup> -->
67e41f4b71Sopenharmony_ci  <div on:click="clickfunc"></div>
68e41f4b71Sopenharmony_ci  <!-- Bind an event callback, but stop the event from bubbling upwards.<sup>5+</sup> -->
69e41f4b71Sopenharmony_ci  <div grab:click.bubble="clickfunc"></div>
70e41f4b71Sopenharmony_ci  <!-- grab:{event} is equivalent to grab:{event}.bubble.<sup>5+</sup> -->
71e41f4b71Sopenharmony_ci  <div grab:click="clickfunc"></div>
72e41f4b71Sopenharmony_ci</div>
73e41f4b71Sopenharmony_ci```
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci```js
77e41f4b71Sopenharmony_ci// xxx.js
78e41f4b71Sopenharmony_ciexport default {
79e41f4b71Sopenharmony_ci  data: {
80e41f4b71Sopenharmony_ci    obj: '',
81e41f4b71Sopenharmony_ci  },
82e41f4b71Sopenharmony_ci  clickfunc: function(e) {
83e41f4b71Sopenharmony_ci    this.obj = 'Hello World';
84e41f4b71Sopenharmony_ci    console.log(e);
85e41f4b71Sopenharmony_ci  },
86e41f4b71Sopenharmony_ci}
87e41f4b71Sopenharmony_ci```
88e41f4b71Sopenharmony_ci
89e41f4b71Sopenharmony_ci>  **NOTE**
90e41f4b71Sopenharmony_ci>
91e41f4b71Sopenharmony_ci>  Event bubbling is supported since API version 5. After you upgrade the SDK and run an existing JavaScript application, events bound using a traditional statement (such as **onclick**) will not bubble. However, if you use the new SDK to repack the JavaScript application, such events will bubble. To avoid service logic errors, replace the traditional statement with one supported by the new SDK. For example, replace **onclick** with **grab:click**.
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ci**Example**
94e41f4b71Sopenharmony_ci
95e41f4b71Sopenharmony_ci```html
96e41f4b71Sopenharmony_ci<!-- xxx.hml -->
97e41f4b71Sopenharmony_ci<div class="container">
98e41f4b71Sopenharmony_ci  <text class="title">{{count}}</text>
99e41f4b71Sopenharmony_ci  <div class="box">
100e41f4b71Sopenharmony_ci    <input type="button" class="btn" value="increase" onclick="increase" />
101e41f4b71Sopenharmony_ci    <input type="button" class="btn" value="decrease" @click="decrease" />
102e41f4b71Sopenharmony_ci    <!-- Pass additional parameters. -->
103e41f4b71Sopenharmony_ci    <input type="button" class="btn" value="double" @click="multiply(2)" />
104e41f4b71Sopenharmony_ci    <input type="button" class="btn" value="decuple" @click="multiply(10)" />
105e41f4b71Sopenharmony_ci    <input type="button" class="btn" value="square" @click="multiply(count)" />
106e41f4b71Sopenharmony_ci  </div>
107e41f4b71Sopenharmony_ci</div>
108e41f4b71Sopenharmony_ci```
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ci```js
112e41f4b71Sopenharmony_ci// xxx.js 
113e41f4b71Sopenharmony_ciexport default {
114e41f4b71Sopenharmony_ci  data: {
115e41f4b71Sopenharmony_ci    count: 0
116e41f4b71Sopenharmony_ci  },
117e41f4b71Sopenharmony_ci  increase() {
118e41f4b71Sopenharmony_ci    this.count++;
119e41f4b71Sopenharmony_ci  },
120e41f4b71Sopenharmony_ci  decrease() {
121e41f4b71Sopenharmony_ci    this.count--;
122e41f4b71Sopenharmony_ci  },
123e41f4b71Sopenharmony_ci  multiply(multiplier) {
124e41f4b71Sopenharmony_ci    this.count = multiplier * this.count;
125e41f4b71Sopenharmony_ci  }
126e41f4b71Sopenharmony_ci};
127e41f4b71Sopenharmony_ci```
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci
130e41f4b71Sopenharmony_ci```css
131e41f4b71Sopenharmony_ci/* xxx.css */
132e41f4b71Sopenharmony_ci.container {
133e41f4b71Sopenharmony_ci    display: flex;
134e41f4b71Sopenharmony_ci    flex-direction: column;
135e41f4b71Sopenharmony_ci    justify-content: center;
136e41f4b71Sopenharmony_ci    align-items: center;
137e41f4b71Sopenharmony_ci    left: 0px;
138e41f4b71Sopenharmony_ci    top: 0px;
139e41f4b71Sopenharmony_ci    width: 454px;
140e41f4b71Sopenharmony_ci    height: 454px;
141e41f4b71Sopenharmony_ci}
142e41f4b71Sopenharmony_ci.title {
143e41f4b71Sopenharmony_ci    font-size: 30px;
144e41f4b71Sopenharmony_ci    text-align: center;
145e41f4b71Sopenharmony_ci    width: 200px;
146e41f4b71Sopenharmony_ci    height: 100px;
147e41f4b71Sopenharmony_ci}
148e41f4b71Sopenharmony_ci.box {
149e41f4b71Sopenharmony_ci    width: 454px;
150e41f4b71Sopenharmony_ci    height: 200px;
151e41f4b71Sopenharmony_ci    justify-content: center;
152e41f4b71Sopenharmony_ci    align-items: center;
153e41f4b71Sopenharmony_ci    flex-wrap: wrap;
154e41f4b71Sopenharmony_ci}
155e41f4b71Sopenharmony_ci.btn {
156e41f4b71Sopenharmony_ci    width: 200px;
157e41f4b71Sopenharmony_ci    border-radius: 0;
158e41f4b71Sopenharmony_ci    margin-top: 10px;
159e41f4b71Sopenharmony_ci    margin-left: 10px;
160e41f4b71Sopenharmony_ci}
161e41f4b71Sopenharmony_ci```
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci
164e41f4b71Sopenharmony_ci## Loop Rendering
165e41f4b71Sopenharmony_ci
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci```html
168e41f4b71Sopenharmony_ci<!-- xxx.hml -->
169e41f4b71Sopenharmony_ci<div class="array-container">
170e41f4b71Sopenharmony_ci  <!-- div loop rendering -->
171e41f4b71Sopenharmony_ci  <!-- By default, $item indicates the element in the array, and $idx indicates the index of the element in the array. -->
172e41f4b71Sopenharmony_ci    <div class="item-container" for="{{array}}" tid="id" onclick="changeText">
173e41f4b71Sopenharmony_ci        <text>{{$idx}}.{{$item.name}}</text>
174e41f4b71Sopenharmony_ci    </div>
175e41f4b71Sopenharmony_ci  <!-- Define the name for an element variable. -->
176e41f4b71Sopenharmony_ci    <div class="item-container" for="{{value in array}}" tid="id" onclick="changeText">
177e41f4b71Sopenharmony_ci        <text>{{$idx}}.{{value.name}}</text>
178e41f4b71Sopenharmony_ci    </div>
179e41f4b71Sopenharmony_ci  <!-- Define an element variable and its index name. -->
180e41f4b71Sopenharmony_ci    <div class="item-container" for="{{(index, value) in array}}" tid="id" onclick="changeText">
181e41f4b71Sopenharmony_ci        <text>{{index}}.{{value.name}}</text>
182e41f4b71Sopenharmony_ci    </div>
183e41f4b71Sopenharmony_ci</div>
184e41f4b71Sopenharmony_ci```
185e41f4b71Sopenharmony_ci
186e41f4b71Sopenharmony_ci
187e41f4b71Sopenharmony_ci```js
188e41f4b71Sopenharmony_ci// xxx.js
189e41f4b71Sopenharmony_ciexport default {
190e41f4b71Sopenharmony_ci  data: {
191e41f4b71Sopenharmony_ci    array: [
192e41f4b71Sopenharmony_ci      {id: 1, name: 'jack', age: 18}, 
193e41f4b71Sopenharmony_ci      {id: 2, name: 'tony', age: 18},
194e41f4b71Sopenharmony_ci    ],
195e41f4b71Sopenharmony_ci  },
196e41f4b71Sopenharmony_ci  changeText: function() {
197e41f4b71Sopenharmony_ci    if (this.array[1].name === "tony"){
198e41f4b71Sopenharmony_ci      this.array.splice(1, 1, {id:2, name: 'Isabella', age: 18});
199e41f4b71Sopenharmony_ci    } else {
200e41f4b71Sopenharmony_ci      this.array.splice(2, 1, {id:3, name: 'Bary', age: 18});
201e41f4b71Sopenharmony_ci    }
202e41f4b71Sopenharmony_ci  },
203e41f4b71Sopenharmony_ci}
204e41f4b71Sopenharmony_ci```
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ci
207e41f4b71Sopenharmony_ci```css
208e41f4b71Sopenharmony_ci.array-container {
209e41f4b71Sopenharmony_ci    width: 100%;
210e41f4b71Sopenharmony_ci    height: 100%;
211e41f4b71Sopenharmony_ci    justify-content: center;
212e41f4b71Sopenharmony_ci    align-items: center;
213e41f4b71Sopenharmony_ci    flex-direction: column;
214e41f4b71Sopenharmony_ci}
215e41f4b71Sopenharmony_ci
216e41f4b71Sopenharmony_ci.item-container {
217e41f4b71Sopenharmony_ci    margin-top: 10px;
218e41f4b71Sopenharmony_ci    width: 200px;
219e41f4b71Sopenharmony_ci    height: 50px;
220e41f4b71Sopenharmony_ci    flex-direction: column;
221e41f4b71Sopenharmony_ci}
222e41f4b71Sopenharmony_ci```
223e41f4b71Sopenharmony_ci
224e41f4b71Sopenharmony_ci
225e41f4b71Sopenharmony_ciThe **tid** attribute accelerates the **for** loop and improves the re-rendering efficiency when data in a loop changes. The **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. The **for** loop supports the following statements:
226e41f4b71Sopenharmony_ci
227e41f4b71Sopenharmony_ci- for="array": **array** is an array object, whose element variable is **$item** by default.
228e41f4b71Sopenharmony_ci
229e41f4b71Sopenharmony_ci- for="v in array": **v** is a custom element variable, whose index is **$idx** by default.
230e41f4b71Sopenharmony_ci
231e41f4b71Sopenharmony_ci- 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.
232e41f4b71Sopenharmony_ci
233e41f4b71Sopenharmony_ci>  **NOTE**
234e41f4b71Sopenharmony_ci>
235e41f4b71Sopenharmony_ci> - Each element in the array must have the data attribute specified by **tid**. Otherwise, an exception may occur.
236e41f4b71Sopenharmony_ci>
237e41f4b71Sopenharmony_ci> - 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.
238e41f4b71Sopenharmony_ci>
239e41f4b71Sopenharmony_ci> - The **tid** field does not support expressions.
240e41f4b71Sopenharmony_ci
241e41f4b71Sopenharmony_ci
242e41f4b71Sopenharmony_ci## Conditional Rendering
243e41f4b71Sopenharmony_ci
244e41f4b71Sopenharmony_ciThere 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:
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci
247e41f4b71Sopenharmony_ci```html
248e41f4b71Sopenharmony_ci<!-- xxx.hml -->
249e41f4b71Sopenharmony_ci<div class="container">
250e41f4b71Sopenharmony_ci  <button class="btn" type="capsule" value="toggleShow" onclick="toggleShow"></button>
251e41f4b71Sopenharmony_ci  <button class="btn" type="capsule" value="toggleDisplay" onclick="toggleDisplay"></button>
252e41f4b71Sopenharmony_ci  <text if="{{show}}"> Hello-One </text>
253e41f4b71Sopenharmony_ci  <text elif="{{display}}"> Hello-Two </text>
254e41f4b71Sopenharmony_ci  <text else> Hello-World </text>
255e41f4b71Sopenharmony_ci</div>
256e41f4b71Sopenharmony_ci```
257e41f4b71Sopenharmony_ci
258e41f4b71Sopenharmony_ci
259e41f4b71Sopenharmony_ci```css
260e41f4b71Sopenharmony_ci/* xxx.css */
261e41f4b71Sopenharmony_ci.container{
262e41f4b71Sopenharmony_ci  flex-direction: column;
263e41f4b71Sopenharmony_ci  align-items: center;
264e41f4b71Sopenharmony_ci}
265e41f4b71Sopenharmony_ci.btn{
266e41f4b71Sopenharmony_ci  width: 280px;
267e41f4b71Sopenharmony_ci  font-size: 26px;
268e41f4b71Sopenharmony_ci  margin: 10px 0;
269e41f4b71Sopenharmony_ci}
270e41f4b71Sopenharmony_ci```
271e41f4b71Sopenharmony_ci
272e41f4b71Sopenharmony_ci
273e41f4b71Sopenharmony_ci```js
274e41f4b71Sopenharmony_ci// xxx.js
275e41f4b71Sopenharmony_ciexport default {
276e41f4b71Sopenharmony_ci  data: {
277e41f4b71Sopenharmony_ci    show: false,
278e41f4b71Sopenharmony_ci    display: true,
279e41f4b71Sopenharmony_ci  },
280e41f4b71Sopenharmony_ci  toggleShow: function() {
281e41f4b71Sopenharmony_ci    this.show = !this.show;
282e41f4b71Sopenharmony_ci  },
283e41f4b71Sopenharmony_ci  toggleDisplay: function() {
284e41f4b71Sopenharmony_ci    this.display = !this.display;
285e41f4b71Sopenharmony_ci  }
286e41f4b71Sopenharmony_ci}
287e41f4b71Sopenharmony_ci```
288e41f4b71Sopenharmony_ci
289e41f4b71Sopenharmony_ciIn the optimized rendering (**show**), if **show** is **true**, the node is rendered properly; if it is **false**, the display style will be **none**.
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci
292e41f4b71Sopenharmony_ci```html
293e41f4b71Sopenharmony_ci<!-- xxx.hml -->
294e41f4b71Sopenharmony_ci<div class="container">
295e41f4b71Sopenharmony_ci  <button class="btn" type="capsule" value="toggle" onclick="toggle"></button>
296e41f4b71Sopenharmony_ci  <text show="{{visible}}" > Hello World </text>
297e41f4b71Sopenharmony_ci</div>
298e41f4b71Sopenharmony_ci```
299e41f4b71Sopenharmony_ci
300e41f4b71Sopenharmony_ci
301e41f4b71Sopenharmony_ci```css
302e41f4b71Sopenharmony_ci/* xxx.css */
303e41f4b71Sopenharmony_ci.container{
304e41f4b71Sopenharmony_ci  flex-direction: column;
305e41f4b71Sopenharmony_ci  align-items: center;
306e41f4b71Sopenharmony_ci}
307e41f4b71Sopenharmony_ci.btn{
308e41f4b71Sopenharmony_ci  width: 280px;
309e41f4b71Sopenharmony_ci  font-size: 26px;
310e41f4b71Sopenharmony_ci  margin: 10px 0;
311e41f4b71Sopenharmony_ci}
312e41f4b71Sopenharmony_ci```
313e41f4b71Sopenharmony_ci
314e41f4b71Sopenharmony_ci
315e41f4b71Sopenharmony_ci```js
316e41f4b71Sopenharmony_ci// xxx.js
317e41f4b71Sopenharmony_ciexport default {
318e41f4b71Sopenharmony_ci  data: {
319e41f4b71Sopenharmony_ci    visible: false,
320e41f4b71Sopenharmony_ci  },
321e41f4b71Sopenharmony_ci  toggle: function() {
322e41f4b71Sopenharmony_ci    this.visible = !this.visible;
323e41f4b71Sopenharmony_ci  },
324e41f4b71Sopenharmony_ci}
325e41f4b71Sopenharmony_ci```
326e41f4b71Sopenharmony_ci
327e41f4b71Sopenharmony_ci>  **NOTE**
328e41f4b71Sopenharmony_ci>
329e41f4b71Sopenharmony_ci>  Do not use **for** and **if** attributes at the same time in an element.
330