1. 程式人生 > >微信小程序開發教程(八)視圖層——.wxml詳解

微信小程序開發教程(八)視圖層——.wxml詳解

span hid 處理 路徑 strong 一般來說 emp 條件 頁面數據

  框架的視圖層由WXMKL(WeiXin Markup language)與WXSS(WeiXin Style Sheet)編寫,由組件進行展示。

  對於微信小程序而言,視圖層就是所有.wxml文件與.wxss文件的集合。

  微信小程序在邏輯層將數據進行處理後發送給視圖層展現出來,同時接受視圖層的事件反饋。

  ? .wxml文件用於描述頁面的結構。

  ? .wxss文件用於描述頁面的樣式。

  視圖層以給定的樣式展現數據並將時間反饋給邏輯層,而數據展現是以組件來進行的。組件(Component)是視圖的基本單元,是構建.wxml文件必不可少的。

  對於小程序的WXML編碼開發,我們基本上可以認為就是使用組件、結合時間系統,構建頁面結構的過程。.wxml文件中所綁定的數據,均來自於對應頁的.js文件中Page方法的data對象。

WXML

  WXML是框架設計的一套類似HTML的標簽語言,結合基礎組件、事件系統,可以構建出頁面的結構,即.wxml文件。

  .wxml文件第一行建議寫<!--頁面名.wxml-->。如:

<!--logs.wxml-->
<view class="container log-list">
    <block wx:for="{{logs}}" wx:for-item="log">
        <text class="log-item">{{index+1}}.{{log}}</text>
    </
block> </view>

  通過<view>組件控制頁面內容展現,通過<block>組件與<text>組件實現頁面數據綁定。

  WXML具有數據綁定、列表渲染、條件渲染、模板及事件綁定的能力。

  數據綁定

  .wxml文件中的動態數據均來自對應頁面的.js文件中Page的data對象。

  (1)簡單綁定

  數據綁定使用Mustache語法(即“雙大括號”語法)將變量包起來。

  a.作用於內容

<!--wxml-->
<view>{{message}}</view>
//page.js
Page({
   date:{
        message:
‘Hello MINA!‘ } })

  b.作用於組件屬性

<!--wxml-->
<view id="item-{{id}}"></view>
//page.js
Page({
    data:{
        id:0
    }
})

  c.控制屬性

<!--wxml-->
<view wx:if="{{condition}}"></view>
//page.js
Page({
    data:{
        condition:true
    }
})

  (2)運算

  可以在{{}}內進行簡單的運算,支持以下幾種方式:①三元運算,②算數運算,③邏輯判斷,④字符串運算,⑤數據路徑運算

<!--wxml-->
<!---->
<view hidden="{{flag ? true : false}}">Hidden</view>

<!---->
<view>{{a + b}} + {{c}} + d </view>
//page.js
Page({
    data:{
        a:1,
        b:2,
        c:3
    }
})

<!---->
<view wx:if="{{length > 5}}"></view>

<!---->
<view>{{"hello" + name}}</view>
//page.js
Page({
    data:{
        name:‘MINA‘
    }
})

<!---->
<view>{{object.key}}{{array[0]}}</view>
//page.js
Page({
   data:{
       object:{
           key:‘Hello‘
       },
      array:[‘MINA‘]
   }
})

  (3)組合

  可以再Mustache內直接進行組合,構成新的對象或者數組。

數組:

<!--wxml-->
<view wx:for="{{zero,1,2,3,4}}">{{item}}</view>
//page.js
Page({
    data:{
        zero:0
    }
})

最終組合成數組[0,1,2,3,4]。

  對象:

<!--wxml-->
<template is="objectCombine" data="{{for:a,bar:b}}"></template>
//page.js
Page({
    data:{
        a:1,
        b:2
    }
})

最終組合成的對象是{{for:1,bar:2}}。

  列表渲染

  列表語句可用於.wxml中進行列表渲染,將列表中的各項數據進行重復渲染。

  (1)wx:for

  在組件上使用wx:for控制屬性綁定一個數組,即可使用數組中各項的數據重復渲染該組件。

  默認數組當前項的下標變量名默認為index,數組當前項的變量名默認為item。

<!--wxml-->
<view wx:for="{{items}}">
  
{{index}}:{{item.message}}
</view>
//page.js
Page({
   data:{
       items:[{
      message:‘foo‘
    },{
      message:‘bar‘
    }]
} })

  ? 使用wx:for-item可以指定數組當前元素的變量名。

  ? 使用wx:for-index可以指定數組當前下標的變量名。

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
    {{idx}}:{{itemName.message}}
</view>

  wx:for也可以嵌套,例如九九乘法表:

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

  條件渲染

  條件語句可用於.wxml中進行條件渲染,不同的條件進行不同的渲染。

  我們用wx:if=“{{condition}}”來判斷是否需要渲染該代碼塊。也可以用wx:elif和wx:else來添加一個else塊。

<!--wxml-->
<view wx:if="{{view == ‘WEBVIEW‘}}">WEBVIEW</view>
<view wx:elif="{{view == ‘APP‘}}">APP</view>
<view wx:else="{{view == ‘MINA‘}}">MINA</view>
//page.js
Page({
    data:{
        view:‘MINA‘
    }
})    

  因為wx:if是一個控制屬性,需要將它添加到一個組件標簽上。如果想一次性判斷多個組件標簽,其實可以使用一個<block/>標簽將多個組件包裝起來,並在其上使用wx:if控制屬性。

<block wx:if="{{true}}">
    <view> view1 </view>
    <view> view2 </view>
</block>
註:<block/>並不是一個組件,他僅僅是一個包裝元素,不會在頁面中做任何渲染,只接受控制屬性。

  

  wx:if 和 hidden的區別:

  因為wx:if之中的模塊也可能包含數據綁定,所以當wx:if的條件值切換時,框架由一個局部渲染的過程,從而確保條件塊在切換時銷毀或重新渲染。

  同時wx:if也是惰性的,如果在初始渲染條件為false,框架什麽也不做,在條件第一次變成真的時候才開始局部渲染。相比之下,hidden就簡單的多,組件始終會被渲染,只需簡單地控制顯示與隱藏。

  一般來說,wx:if有更高的切換消耗,而hidden有更高的初始渲染消耗。因此,如果需要頻繁切換的情況下,用hidden更好;如果運行時條件不大可能改變,則wx:if較好。

  模板

  WXML支持模板(template),可以在模板中定義代碼片段,然後在不同的地方調用。

  使用name屬性,作為模板的名字。使用is屬性,聲明需要使用的模板,然後將模板所需要的data傳入。

<!--wxml-->
<template name="staffName">
    <view>
        FirstName:{{firstName}},LastName:{{lastName}}
    </view>
</template>

<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
//page.js
Page({
   date:{
       staffA:{firstName:‘Hulk‘,lastName:‘Hu‘},
       staffB:{firstName:‘Shang‘,lastName:‘You‘},
       staffC:{firstName:‘Gideon‘,lastName:‘Lin‘}, 
   } 
})

  字例代碼中,“...”為擴展運算符,用來展開一個對象,如staffA對象。

  is屬性可以使用Mustache,來動態決定具體需要渲染哪個模板:

<template name="odd">
    <view> odd </view>
</template>
<template name="even">
    <view> even </view>
</template>

<block wx:for="{{[1,2,3,4,5]}}">
    <template is="{{item % 2 == 0 ? ‘even‘ : ‘odd‘}}">
</block>

  模板擁有自己的作用域,只能使用data傳入的數據。

  事件綁定

  事件的定義如下:

  ? 事件是視圖層到邏輯層的通信方式。

  ? 事件可以將用戶的行為反饋到邏輯層進行處理。

  ? 事件可以綁定在組件上,當達到觸發事件,就會執行邏輯層中對應的事件處理函數。

  ? 事件對象可以攜帶額外信息,如id、dataset、touches。

  我們小程序與用戶交互,多數情況下是通過事件來進行的。首先,在組件中綁定一個事件處理函數。在下面代碼中,我們使用bindtap,當用戶點擊該組件view時會在該頁面對應Page中找到相應的事件處理函數add。

<!--wxml-->
<!--指定view組件的唯一標識tapTest;自定義屬性hi,其值為MINA;綁定事件add-->
<view id="tapTest" data-hi="MINA" bindtap="add">{{count}}</view>
註:應將bindtap理解為:bind+tap,即綁定冒泡事件tap(手指觸摸後離開)。

  其次,在相應的Page定義中寫上相應的事件處理函數。

//page.js
Page({
    data:{
        count:1
    },
    add:function(e){
        this.setData({
            count:this.data.count + 1
        })
    }
})

  事件詳解

  微信小程序裏的事件分為冒泡事件和非冒泡事件:

  ? 冒泡事件:當一個組件上的事件被觸發後,該事件會向父節點傳遞。

  ? 非冒泡事件:當一個組件上的事件被觸發後,改時間不會向父節點傳遞。

  WXML中的冒泡事件僅有6個

技術分享

  除上表之外的其他組件自定義時間都是非冒泡事件。

  事件綁定的寫法同組件屬性,以key,value的形式。

  ? key以bind或touch開頭,然後跟上事件的類型,如bindtap、catchtouchstart。

  ? value是一個字符串,需要在對應的Page中定義同名的函數。不然當觸發事件的時候會報錯。

註:bind事件綁定不會阻止冒泡事件向上冒泡,catch事件綁定可以阻止冒泡事件向上冒泡。

  看一個例子:

<view id="outter" bindtap="handleTap1">
    outer view
    <view id="middle" catchtap="handleTap2">
        middle view
        <view id="inner" catchtap="handleTap3">
            inner view
        </view>
    </view>
</view>

  點擊id為inner的組件會先後觸發handleTap3和handleTap2,不會觸發handleTap1。

  如無特殊說明,當組件觸發事件時,邏輯層綁定該事件的處理函數會收到一個事件對象,事件對象具有屬性如下:

  BaseEvent 基礎事件對象屬性列表:

  技術分享

  CustomEvent 自定義事件對象屬性列表(繼承 BaseEvent):

  技術分享

  TouchEvent 觸摸事件對象屬性列表(繼承 BaseEvent):

  技術分享

  特殊事件: <canvas/> 中的觸摸事件不可冒泡,所以沒有 currentTarget。

  ? type:通用事件類型。

  ? timeStamp:頁面打開到觸發事件所經過的毫秒數

  ? target:觸發事件的源組件。是一個對象,具有以下三個屬性:

  技術分享

  ? currentTarget:事件綁定的當前組件。與target類似,是一個對象,同樣具有上表三個屬性。

  ? touches:觸摸點數組,每個觸摸點包含以下屬性。

  技術分享

  ? changedTouches:數據格式同touches。表示有變化的觸摸點。

  ? detail:指特殊事件所攜帶的數據。如表單組件的提交事件會攜帶用戶的輸入,媒體的錯誤事件會攜帶錯誤信息。

  引用

  WXML提供兩種文件引入方式:import和include。

  (1)import

  import可以在該文件中使用目標文件定義的template,例如:在item.wxml中定義了一個叫item的template:

<!--item.wxml-->
<template name="item">
    <text>{{text}}</text>
</template>

  在index.wxml中引用了item.wxml,就可以使用item模板:

<import src="item.wxml">
<template is="item" data="{{text:‘forbar‘}}"/>

  import有作用域,只會引用目標文件中定義的template,而不會引用目標文件嵌套import的template。

  (2)include

  include可將目標文件除模板代碼(<template/>)塊的所有代碼引入,相當於拷貝到include位置,如:

<!--index.wxml-->
<include src="header.wxml"/>
<view> body</view>
<include src="footer.wxml"/>

<!--header.wxml-->
<view> header </view>
<!--footer.wxml-->
<view> footer </view>

微信小程序開發教程(八)視圖層——.wxml詳解