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