Introduction

The suffix of the presentation file is “axml”, which defines the label structure of the page. Here are some examples to demonstrate the capabilities of “axml”.

Data binding:

  1. <view> {{message}} </view>
  1. // page.js
  2. Page({
  3. data: {
  4. message: 'Hello alipay!'
  5. }
  6. })

List rendering:

  1. <view a:for="{{items}}"> {{item}} </view>
  1. // page.js
  2. Page({
  3. data: {
  4. items: [1, 2, 3, 4, 5, 6, 7]
  5. }
  6. })

Conditional rendering:

  1. <view a:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
  2. <view a:elif="{{view == 'APP'}}"> APP </view>
  3. <view a:else="{{view == 'alipay'}}"> alipay </view>
  1. // page.js
  2. Page({
  3. data: {
  4. view: 'alipay'
  5. }
  6. })

Template:

  1. <template name="staffName">
  2. <view>
  3. FirstName: {{firstName}}, LastName: {{lastName}}
  4. </view>
  5. </template>
  6. <template is="staffName" data="{{...staffA}}"></template>
  7. <template is="staffName" data="{{...staffB}}"></template>
  8. <template is="staffName" data="{{...staffC}}"></template>
  1. // page.js
  2. // Hats off to the Wechat Mini Program engineers.
  3. Page({
  4. data: {
  5. staffA: {
  6. firstName: 'san',
  7. lastName: 'zhang'
  8. },
  9. staffB: {
  10. firstName: 'si',
  11. lastName: 'li'
  12. },
  13. staffC: {
  14. firstName: 'wu',
  15. lastName: 'wang'
  16. },
  17. },
  18. })

Event:

  1. <view onTap="add"> {{count}} </view>
  1. Page({
  2. data: {
  3. count: 1
  4. },
  5. add(e) {
  6. this.setData({
  7. count: this.data.count + 1
  8. })
  9. }
  10. })

Data binding

The dynamic data in “axml” come from the “data”in“Page”.

Simple binding

“Mustache syntax” (double brackets) inis used data bindingto wrap up variables, which can be applied in various situations including content. For example:

  1. <view> {{ message }} </view>
  1. Page({
  2. data: {
  3. message: 'Hello alipay!'
  4. }
  5. })

It is applied in component attribute (which needs to be enclosed in double quotes), for example:

  1. <view id="item-{{id}}"> </view>
  1. Page({
  2. data: {
  3. id: 0
  4. }
  5. })

Acts on control attributes (need to be within double quotes), e.g:

  1. <view a:if="{{condition}}"> </view>
  1. Page({
  2. data: {
  3. condition: true
  4. }
  5. })

It is applied in keywords(which need to be enclosed in double quotes), for example:

  1. <checkbox checked="{{false}}"> </checkbox>
  • true:“ true” of boolean type, represents the truth value.
  • false:“false” of boolean type, represents a false value.

    Note: Don’t write “checked=”false” directly. The calculationresult is a string, which will represent “true” when converted to a Boolean value type.

Simple calculations can be performed in {{}}, and here are following methods:

Ternary operation:

  1. <view hidden="{{flag ? true : false}}"> Hidden </view>

Arithmetic operation:

  1. <view> {{a + b}} + {{c}} + d </view>
  1. Page({
  2. data: {
  3. a: 1,
  4. b: 2,
  5. c: 3
  6. }
  7. })

The contents of the View are 3 + 3 + d.

Logical judgment:

  1. <view a:if="{{length > 5}}"> </view>

String operation:

  1. <view>{{"hello" + name}}</view>
  1. Page({
  2. data: {
  3. name: 'alipay'
  4. }
  5. })

Data path operation:

  1. <view>{{object.key}} {{array[0]}}</view>
  1. Page({
  2. data: {
  3. object: {
  4. key: 'Hello '
  5. },
  6. array: ['alipay']
  7. }
  8. })

It can also be combined directly in “Mustache” to form a new array or an object.

Array:

  1. <view a:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
  1. Page({
  2. data: {
  3. zero: 0
  4. }
  5. })

The final combined array is [0, 1, 2, 3, 4].

Object:

  1. <template is="objectCombine" data="{{foo: a, bar: b}}"></template>
  1. Page({
  2. data: {
  3. a: 1,
  4. b: 2
  5. }
  6. })

The final combined object is {foo: 1, bar: 2}.

You can also use the spread operator… to expand an object.

  1. <template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>
  1. Page({
  2. data: {
  3. obj1: {
  4. a: 1,
  5. b: 2
  6. },
  7. obj2: {
  8. c: 3,
  9. d: 4
  10. }
  11. }
  12. })

The final combined object is {a: 1, b: 2, c: 3, d: 4, e: 5}.

If the “key” and “value” of the object are the same, they can also be expressed indirectly.

  1. <template is="objectCombine" data="{{foo, bar}}"></template>
  1. Page({
  2. data: {
  3. foo: 'my-foo',
  4. bar: 'my-bar'
  5. }
  6. })

The final combined object is {foo: ‘my-foo’, bar:’ my-bar’ }.

Note: The above methods can be combined randomly, but if there are cases where the variable names are the same, the following variables will override the previous variables.

  1. <template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template>
  1. Page({
  2. data: {
  3. obj1: {
  4. a: 1,
  5. b: 2
  6. },
  7. obj2: {
  8. b: 3,
  9. c: 4
  10. },
  11. a: 5
  12. }
  13. })

The final combined object is {a: 5, b: 3, c: 6}.

Conditional rendering

a:if

In the framework, you can use a:if=”{{condition}}” to decide on whether the code block needs to be rendered.

  1. <view a:if="{{condition}}"> True </view>

You can also use “a:elif” and “a:else” to add an “else” block.

  1. <view a:if="{{length > 5}}"> 1 </view>
  2. <view a:elif="{{length > 2}}"> 2 </view>
  3. <view a:else> 3 </view>

block a:if

Due tothe control attribute of “a:if”, it needs to be added to a label. If you want to judge multiple component tags at once, you can use a tag to wrap multiple components, and use a:if on it to control the attributes.

  1. <block a:if="{{true}}">
  2. <view> view1 </view>
  3. <view> view2 </view>
  4. </block>

Note: is not a component, but just a packaging element,which will not do any rendering in the page and only accept control attributes.

List rendering

a:for

You can bind an array with the “a:for” attribute on the component before rendering the component repeatedly with the data in the array. The subscript variable name of the current item in the array is“index” by default, and the variable name of the current item in the array is “item” by default.

  1. <view a:for="{{array}}">
  2. {{index}}: {{item.message}}
  3. </view>
  1. Page({
  2. data: {
  3. array: [{
  4. message: 'foo',
  5. },
  6. {
  7. message: 'bar'
  8. }]
  9. }
  10. })

Use “a:for-item” to specify the variable name of the current element of the array.

Use “a:for-index” to specify the variable name of thecurrent subscript of the array.

  1. <view a:for="{{array}}" a:for-index="idx" a:for-item="itemName">
  2. {{idx}}: {{itemName.message}}
  3. </view>

“a:for” can also be nested. And the following is a code example of the multiplication table:

  1. <view a:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" a:for-item="i">
  2. <view a:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" a:for-item="j">
  3. <view a:if="{{i <= j}}">
  4. {{i}} * {{j}} = {{i * j}}
  5. </view>
  6. </view>
  7. </view>

block a:for

Similar to “block a:if”, you can also use “a:for” on the tag to render a structure block containing multiple nodes.

  1. <block a:for="{{[1, 2, 3]}}">
  2. <view> {{index}}: </view>
  3. <view> {{item}} </view>
  4. </block>

a:key

If the position of an item in the list changes dynamically or a new item is added to the list with the items maintaining their own characteristics and state (like the input content in , ), you need to use “a:key” to specify the unique identifier of the item in the list.

The value of “a:key is provided in two forms:

  • A string represents a certain attribute of “item” in the “array” of the “for”cycle. The value of this attribute needs to be the only string or number in the list and cannot be changed dynamically.
  • The reserved keyword “*this” represents the “item” itself in the “for”cycle, indicating that the “item” itself is required to be a unique string or number. For example, when the data change triggers the rendering layer to re-execute the rendering, the components with the “key” will be corrected. And the framework will ensure that they are reordered rather than re-created so as to make the components remain their own stateand improve the efficiency of list rendering.

If you know that the list is static or don’t notice its order, you can ignore it.

Code example:

  1. <view class="container">
  2. <view a:for="{{list}}" a:key="*this">
  3. <view onTap="bringToFront" data-value="{{item}}">
  4. {{item}}: click to bring to front
  5. </view>
  6. </view>
  7. </view>
  1. Page({
  2. data: {
  3. list: ['1', '2', '3', '4'],
  4. },
  5. bringToFront(e) {
  6. const {
  7. value
  8. } = e.target.dataset;
  9. const list = this.data.list.concat();
  10. const index = list.indexOf(value);
  11. if (index !== -1) {
  12. list.splice(index, 1);
  13. list.unshift(value);
  14. this.setData({
  15. list
  16. });
  17. }
  18. }
  19. });

key

“key” is a more universal way of writing than “a:key”, which can be filled with any expression and string.

Code example:

  1. <view class="container">
  2. <view a:for="{{list}}" key="{{item}}">
  3. <view onTap="bringToFront" data-value="{{item}}">
  4. {{item}}: click to bring to front
  5. </view>
  6. </view>
  7. </view>
  1. Page({
  2. data: {
  3. list: ['1', '2', '3', '4'],
  4. },
  5. bringToFront(e) {
  6. const {
  7. value
  8. } = e.target.dataset;
  9. const list = this.data.list.concat();
  10. const index = list.indexOf(value);
  11. if (index !== -1) {
  12. list.splice(index, 1);
  13. list.unshift(value);
  14. this.setData({
  15. list
  16. });
  17. }
  18. }
  19. });

Meanwhile, the “key” can be used to prevent the reuse of components. For example, if users are allowed to input different types of data:

  1. <input a:if="{{name}}" placeholder="Enter your username">
  2. <input a:else placeholder="Enter your email address">

Then when you input “name” and switch to “email”, the current input value will be retained. If you don’t want to retain it, you can add “key”:

  1. <input key="name" a:if="{{name}}" placeholder="Enter your username">
  2. <input key="email" a:else placeholder="Enter your email address">

Reference

“axml” provides two file reference methods: “import” and “include”.

import

“import” can load the “template” that has been defined.

For example, a “template”named “item” is defined in “item.axml”.

  1. <!-- item.axml -->
  2. <template name="item">
  3. <text>{{text}}</text>
  4. </template>

You can use the“item” template after the reference of“item.axml” in “index.axml”.

  1. <import src="./item.axml"/>
  2. <template is="item" data="{{text: 'forbar'}}"/>

Only the “template” defined in the target file will be imported due to the scope concept of “import”. For example, C import B. B import A.The “template” defined by B can be used in C, and the “template” defined by A can be used in B, but the “template” defined in A cannot be used in C.

  1. <!-- A.axml -->
  2. <template name="A">
  3. <text> A template </text>
  4. </template>
  1. <!-- B.axml -->
  2. <import src="./a.axml"/>
  3. <template name="B">
  4. <text> B template </text>
  5. </template>
  1. <!-- C.axml -->
  2. <import src="./b.axml"/>
  3. <template is="A"/> <!-- Error! Can not use tempalte when not import A. -->
  4. <template is="B"/>

Note:The sub-node of “template” can only be one rather than multiple ones.For example:
Allowing

  1. <template name="x">
  2. <view />
  3. </template>

Not allowing

  1. <template name="x">
  2. <view />
  3. <view />
  4. </template>

include

“include” can import the entire code of the target file except , which is an equivalent of copy in the “include”. The code example is as follows:

  1. <!-- index.axml -->
  2. <include src="./header.axml"/>
  3. <view> body </view>
  4. <include src="./footer.axml"/>
  1. <!-- header.axml -->
  2. <view> header </view>
  1. <!-- footer.axml -->
  2. <view> footer </view>

Template

“axml” provides template, in which you can define code snippets and call them in different places.

Define the template

Use the “name” attribute as the name of the template, and then define the code snippets within .

  1. <!--
  2. index: int
  3. msg: string
  4. time: string
  5. -->
  6. <template name="msgItem">
  7. <view>
  8. <text> {{index}}: {{msg}} </text>
  9. <text> Time: {{time}} </text>
  10. </view>
  11. </template>

Use templates

Use the “is” attribute to declare the template to be used, and then import the data required by the template.For example:

  1. <template is="msgItem" data="{{...item}}"/>
  1. Page({
  2. data: {
  3. item: {
  4. index: 0,
  5. msg: 'this is a template',
  6. time: '2016-09-15'
  7. }
  8. }
  9. })

“Mustache syntax” can be used by “is” attribute to dynamically decide on which template needs to be rendered.

  1. <template name="odd">
  2. <view> odd </view>
  3. </template>
  4. <template name="even">
  5. <view> even </view>
  6. </template>
  7. <block a:for="{{[1, 2, 3, 4, 5]}}">
  8. <template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>
  9. </block>

Note: With its own scope, the template can only use the data passed by “data”.But it can bind the logical processing function of the page through onXX.

It is recommended to use the “template” method to import the template snippets because the template will specify its own scope and only use the data passed in by “data”. And mini programs will optimize this accordingly. If the “data” of the “template” does not change, the snippet UI will not be re-rendered. The reference path supports loading the third module from the “node_modules” directory such as “page.axml”:

  1. <import src="./a.axml"/> <!-- 相对路径 -->
  2. <import src="/a.axml"/> <!-- 项目绝对路径 -->
  3. <import src="third-party/x.axml"/> <!-- 第三方 npm 包路径 -->