1# HML语法参考<a name="ZH-CN_TOPIC_0000001163812206"></a> 2 3HML(OpenHarmony Markup Language)是一套类HTML的标记语言,通过组件,事件构建出页面的内容。页面具备数据绑定、事件绑定、列表渲染、条件渲染和逻辑控制等高级能力。 4 5## 页面结构<a name="zh-cn_topic_0000001127284830_section1062764791514"></a> 6 7``` 8<!-- xxx.hml --> 9<div class="item-container"> 10 <text class="item-title">Image Show</text> 11 <div class="item-content"> 12 <image src="/common/xxx.png" class="image"></image> 13 </div> 14</div> 15``` 16 17## 数据绑定<a name="zh-cn_topic_0000001127284830_s8821c158917c48098219013e69129d1b"></a> 18 19``` 20<!-- xxx.hml --> 21<div onclick="changeText"> 22 <text> {{content[1]}} </text> 23</div> 24``` 25 26``` 27// xxx.js 28export default { 29 data: { 30 content: ['Hello World!', 'Welcome to my world!'] 31 }, 32 changeText: function() { 33 this.content.splice(1, 1, this.content[0]); 34 } 35} 36``` 37 38> **说明:** 39>- 针对数组内的数据修改,请使用splice方法生效数据绑定变更。 40>- hml文件中的js表达式不支持ES6语法。 41 42## 普通事件绑定<a name="zh-cn_topic_0000001127284830_section193010312423"></a> 43 44事件通过'on'或者'@'绑定在组件上,当组件触发事件时会执行JS文件中对应的事件处理函数。 45 46事件支持的写法有: 47 48- "funcName":funcName为事件回调函数名(在JS文件中定义相应的函数实现)。 49- "funcName\(a,b\)":函数参数例如a,b可以是常量,或者是在JS文件中的data中定义的变量(前面不用写this.)。 50 51- **示例** 52 53 ``` 54 <!-- xxx.hml --> 55 <div class="container"> 56 <text class="title">{{count}}</text> 57 <div class="box"> 58 <input type="button" class="btn" value="increase" onclick="increase" /> 59 <input type="button" class="btn" value="decrease" @click="decrease" /> 60 <!-- 传递额外参数 --> 61 <input type="button" class="btn" value="double" @click="multiply(2)" /> 62 <input type="button" class="btn" value="decuple" @click="multiply(10)" /> 63 <input type="button" class="btn" value="square" @click="multiply(count)" /> 64 </div> 65 </div> 66 ``` 67 68 ``` 69 /* xxx.js */ 70 export default { 71 data: { 72 count: 0 73 }, 74 increase() { 75 this.count++; 76 }, 77 decrease() { 78 this.count--; 79 }, 80 multiply(multiplier) { 81 this.count = multiplier * this.count; 82 } 83 }; 84 ``` 85 86 ``` 87 /* xxx.css */ 88 .container { 89 display: flex; 90 flex-direction: column; 91 justify-content: center; 92 align-items: center; 93 left: 0px; 94 top: 0px; 95 width: 454px; 96 height: 454px; 97 } 98 .title { 99 font-size: 30px; 100 text-align: center; 101 width: 200px; 102 height: 100px; 103 } 104 .box { 105 width: 454px; 106 height: 200px; 107 justify-content: center; 108 align-items: center; 109 flex-wrap: wrap; 110 } 111 .btn { 112 width: 200px; 113 border-radius: 0; 114 margin-top: 10px; 115 margin-left: 10px; 116 } 117 ``` 118 119 120## 冒泡事件绑定<sup>5+</sup><a name="zh-cn_topic_0000001127284830_section368561455815"></a> 121 122冒泡事件绑定包括: 123 124- 绑定冒泡事件:on:\{event\}.bubble。on:\{event\}等价于on:\{event\}.bubble。 125- 绑定并阻止冒泡事件向上冒泡:grab:\{event\}.bubble。grab:\{event\}等价于grab:\{event\}.bubble。 126 127 > **说明:** 128 >详细冒泡事件说明参见[通用事件](component/js-components-common-events.md)章节。 129 130 131- **示例** 132 133 ``` 134 <div> 135 <!-- 使用事件冒泡模式绑定事件回调函数。5+ --> 136 <div on:touchstart.bubble="touchstartfunc"></div> 137 <div on:touchstart="touchstartfunc"></div> 138 <!-- 绑定事件回调函数,但阻止事件向上传递。5+ --> 139 <div grab:touchstart.bubble="touchstartfunc"></div> 140 <div grab:touchstart="touchstartfunc"></div> 141 <!-- 使用事件冒泡模式绑定事件回调函数。6+ --> 142 <div on:click.bubble="clickfunc"></div> 143 <div on:click="clickfunc"></div> 144 <!-- 绑定事件回调函数,但阻止事件向上传递。6+ --> 145 <div grab:click.bubble="clickfunc"></div> 146 <div grab:click="clickfunc"></div> 147 </div> 148 ``` 149 150 ``` 151 // xxx.js 152 export default { 153 clickfunc: function(e) { 154 console.log(e); 155 }, 156 touchstartfuc: function(e) { 157 console.log(e); 158 }, 159 } 160 ``` 161 162 163> **说明:** 164>- 采用旧写法\(onclick\)的事件绑定在最小API版本6以下时采用不冒泡处理,在最小API版本为6及6以上时采用冒泡处理。 165 166## 捕获事件绑定<sup>5+</sup><a name="zh-cn_topic_0000001127284830_section5527539989"></a> 167 168Touch触摸类事件支持捕获,捕获阶段位于冒泡阶段之前,捕获事件先到达父组件然后达到子组件。 169 170捕获事件绑定包括: 171 172- 绑定捕获事件:on:\{event\}.capture。 173- 绑定并阻止事件向下传递:grab:\{event\}.capture。 174 175- **示例** 176 177 ``` 178 <div> 179 <!-- 使用事件捕获模式绑定事件回调函数。5+ --> 180 <div on:touchstart.capture="touchstartfunc"></div> 181 <!-- 绑定事件回调函数,但阻止事件向下传递。5+ --> 182 <div grab:touchstart.capture="touchstartfunc"></div> 183 </div> 184 ``` 185 186 ``` 187 // xxx.js 188 export default { 189 touchstartfuc: function(e) { 190 console.log(e); 191 }, 192 } 193 ``` 194 195 196## 列表渲染<a name="zh-cn_topic_0000001127284830_sb777d6d807fa43fea9be400b2600425b"></a> 197 198``` 199<!-- xxx.hml --> 200<div class="array-container"> 201 <!-- div列表渲染 --> 202 <!-- 默认$item代表数组中的元素, $idx代表数组中的元素索引 --> 203 <div for="{{array}}" tid="id" onclick="changeText"> 204 <text>{{$idx}}.{{$item.name}}</text> 205 </div> 206 <!-- 自定义元素变量名称 --> 207 <div for="{{value in array}}" tid="id" onclick="changeText"> 208 <text>{{$idx}}.{{value.name}}</text> 209 </div> 210 <!-- 自定义元素变量、索引名称 --> 211 <div for="{{(index, value) in array}}" tid="id" onclick="changeText"> 212 <text>{{index}}.{{value.name}}</text> 213 </div> 214</div> 215``` 216 217``` 218// xxx.js 219export default { 220 data: { 221 array: [ 222 {id: 1, name: 'jack', age: 18}, 223 {id: 2, name: 'tony', age: 18}, 224 ], 225 }, 226 changeText: function() { 227 if (this.array[1].name === "tony"){ 228 this.array.splice(1, 1, {id:2, name: 'Isabella', age: 18}); 229 } else { 230 this.array.splice(2, 1, {id:3, name: 'Bary', age: 18}); 231 } 232 }, 233} 234``` 235 236tid属性主要用来加速for循环的重渲染,旨在列表中的数据有变更时,提高重新渲染的效率。tid属性是用来指定数组中每个元素的唯一标识,如果未指定,数组中每个元素的索引为该元素的唯一id。例如上述tid="id"表示数组中的每个元素的id属性为该元素的唯一标识。for循环支持的写法如下: 237 238- for="array":其中array为数组对象,array的元素变量默认为$item。 239- for="v in array":其中v为自定义的元素变量,元素索引默认为$idx。 240- for="\(i, v\) in array":其中元素索引为i,元素变量为v,遍历数组对象array。 241 242> **说明:** 243>- 数组中的每个元素必须存在tid指定的数据属性,否则运行时可能会导致异常。 244>- 数组中被tid指定的属性要保证唯一性,如果不是则会造成性能损耗。比如,示例中只有id和name可以作为tid字段,因为它们属于唯一字段。 245>- tid不支持表达式。 246 247## 条件渲染<a name="zh-cn_topic_0000001127284830_sf7f6eab2105a4030a1f34149417d6fc5"></a> 248 249条件渲染分为2种:if/elif/else和show。两种写法的区别在于:第一种写法里if为false时,组件不会在vdom中构建,也不会渲染,而第二种写法里show为false时虽然也不渲染,但会在vdom中构建;另外,当使用if/elif/else写法时,节点必须是兄弟节点,否则编译无法通过。实例如下: 250 251``` 252<!-- xxx.hml --> 253<div class="container"> 254 <button class="btn" type="capsule" value="toggleShow" onclick="toggleShow"></button> 255 <button class="btn" type="capsule" value="toggleDisplay" onclick="toggleDisplay"></button> 256 <text if="{{visible}}"> Hello-TV </text> 257 <text elif="{{display}}"> Hello-Wearable </text> 258 <text else> Hello-World </text> 259</div> 260``` 261 262``` 263// xxx.css 264.container{ 265 flex-direction: column; 266 align-items: center; 267} 268.btn{ 269 width: 280px; 270 font-size: 26px; 271 margin: 10px 0; 272} 273``` 274 275``` 276// xxx.js 277export default { 278 data: { 279 visible: false, 280 display: true, 281 }, 282 toggleShow: function() { 283 this.visible = !this.visible; 284 }, 285 toggleDisplay: function() { 286 this.display = !this.display; 287 } 288} 289``` 290 291优化渲染优化:show方法。当show为true时,节点正常渲染;当为false时,仅仅设置display样式为none。 292 293``` 294<!-- xxx.hml --> 295<div class="container"> 296 <button class="btn" type="capsule" value="toggle" onclick="toggle"></button> 297 <text show="{{visible}}" > Hello World </text> 298</div> 299``` 300 301``` 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// xxx.js 316export default { 317 data: { 318 visible: false, 319 }, 320 toggle: function() { 321 this.visible = !this.visible; 322 }, 323} 324``` 325 326> **说明:** 327>禁止在同一个元素上同时设置for和if属性。 328 329## 逻辑控制块<a name="zh-cn_topic_0000001127284830_s185169def14340fcbb12c3375cb0f0bb"></a> 330 331<block\>控制块使得循环渲染和条件渲染变得更加灵活;block在构建时不会被当作真实的节点编译。注意block标签只支持for和if属性。 332 333``` 334<!-- xxx.hml --> 335<list> 336 <block for="glasses"> 337 <list-item type="glasses"> 338 <text>{{$item.name}}</text> 339 </list-item> 340 <block for="$item.kinds"> 341 <list-item type="kind"> 342 <text>{{$item.color}}</text> 343 </list-item> 344 </block> 345 </block> 346</list> 347``` 348 349``` 350// xxx.js 351export default { 352 data: { 353 glasses: [ 354 {name:'sunglasses', kinds:[{name:'XXX',color:'XXX'},{name:'XXX',color:'XXX'}]}, 355 {name:'nearsightedness mirror', kinds:[{name:'XXX',color:'XXX'}]}, 356 ], 357 }, 358} 359``` 360 361## 模板引用<a name="zh-cn_topic_0000001127284830_section1388145672114"></a> 362 363HML可以通过element引用模板文件,详细介绍可参考[自定义组件](component/js-components-custom-basic-usage.md)章节。 364 365``` 366<!-- template.hml --> 367<div class="item"> 368 <text>Name: {{name}}</text> 369 <text>Age: {{age}}</text> 370</div> 371``` 372 373``` 374<!-- index.hml --> 375<element name='comp' src='../../common/template.hml'></element> 376<div> 377 <comp name="Tony" age="18"></comp> 378</div> 379``` 380 381