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