
壹 ❀ 引
我在從零開始的微信小程序入門教程(二),初識WXML與WXSS一文中簡單介紹了小程序組件與小程序樣式相關概念,在瞭解這二者以後,其實咱們已經能夠搭建出簡單的靜態頁面,與書寫HTML頁面同樣,小程序頁面也只能經過多寫多練提高。在構建完頁面後就出現了一個問題,咱們該如何獲取組件元素讓數據與之關聯呢?javascript
在網頁開發中,咱們一樣使用JS操做DOM,包括數據渲染,事件監聽等,好比我如今要經過點擊一個按鈕後,替換段落中的本文信息,使用JS能夠這麼作:css
<p>我是誰?</p> <button>點我點我</button>
let btn = document.querySelector("button"), p = document.querySelector("p"); btn.onclick = function () { p.innerHTML = '我是聽風是風啊!' };

沒問題,效果雖然實現了,可是相似的操做咱們老是得獲取並操做DOM,邏輯層與渲染層高度耦合,每一份數據咱們彷佛都得找到對應的DOM所在,並幫助它們相互關聯,這很明顯不太友好。伴隨發展,angularjs,vue,react的出現,咱們知道了MVVM模式的存在,在開發中邏輯層與渲染也得以分離,微信小程序在開發模式上也借鑑了這一點,好比仍是上面的效果,用小程序就能夠這麼作,咱們分別在index.wxhl
和index.js
中添加以下代碼:html
<text>{{myName}}</text> <button bindtap="setName">點我點我</button>
const app = getApp() Page({ data: { myName:'我是誰?' }, setName() { this.setData({ myName: "噴火龍" }) } })

接下來咱們解釋下小程序數據綁定到底怎麼玩,以及其它幾種常見的數據交互方式。vue
貳 ❀ 數據交互
貳 ❀ 壹 數據綁定{{}}
熟悉vue等相關框架的同窗對於上述例子必定十分熟悉,對於第一次瞭解這種用法的同窗也不用擔憂,並不複雜,咱們來解釋下到底什麼是意思。java
首先看WXML,小程序使用{{}}
表達式來綁定解析JS文件中定義的變量,而在JS文件的data對象中通常用於定義小程序初始化所需數據,好比例子中的變量myName
有一個初始值。react
Page({ data: { /* 頁面初始數據寫在這*/ } })
接下來就是如何經過點擊事件讓myName
發生變化,在組件button
上咱們經過點擊事件bindtap
綁定了一個setName
方法,注意,這個方法一樣定義在JS文件Page對象中,與data對象同級,以往咱們綁定方法通常會給方法名後帶括號,小程序的方法綁定並無括號,好比上面的bindtap="setName"
。angularjs
Page({ data: { /* 頁面初始數據寫在這 */ }, 方法名() { /* do something */ } });
數據綁定除了能用於解決組件文本內容的變動,還有一大做用就是支持組件屬性動態變動,什麼是組件屬性?樣式class是屬性,組件內連樣式style也是屬性,好比咱們能夠有這樣一個組件:小程序
<text class="name" style="color:#fff;background:#e4393c">{{myName}}</text>
那麼經過數據綁定表達式,咱們可讓樣式也動起來,好比下面這個例子:微信小程序
<text class="{{defaultClass}}" style="color:#fff;background:{{backgroudColor}};display:block">{{myName}}</text> <button bindtap="setName">點我</button>
.my-name { height: 30px; width: 100px; text-align: center; line-height: 30px; } .my-name-new{ height: 40px; width: 200px; text-align: center; line-height: 40px; }
const app = getApp() Page({ data: { myName: '我是誰?', defaultClass: 'my-name', backgroudColor: '#e4393c' }, setName() { this.setData({ myName: "噴火龍", defaultClass:'my-name-new', backgroudColor:'#bbded6' }) } })

在這個例子中,咱們定義了一個class變量,此class默認值由JS文件中提供,除此以外,在內聯樣式style中的background
屬性也是變量,當點擊按鈕,咱們切換了class的值以及background
的值,在爲屬性使用數據綁定時,惟一須要注意的是{{}}始終被包裹在一對雙引號中,關於數據綁定先說到這裏,也算是WXSS的一部分補充。數組
貳 ❀ 貳 基本邏輯語法
{{}}
中除了單純的解析變量,還能作簡單的邏輯運算,好比算術計算:
<text>{{num1+num2}}</text>
Page({ data: { num1: 1, num2: 2 }, })
咱們還能用於字符串拼接,好比下面的例子:
<text>聽風是風{{str}}</text>
<text>{{"聽風是風"+str}}</text>
Page({ data: { str: '很酷' }, })
這兩種拼接方式都是能夠的,由於在{{}}
中解析的是變量,因此自己是字符時得加上引號。
另外,{{}}
中還能使用三元表達式,也就是根據條件決定使用不一樣的結果:
<text>{{userName?userName:'登陸'}}</text>
Page({ data: { userName: '' }, })
好比上面這個例子就是一個簡單的用戶信息展現,若是有數據展現用戶名,若是沒有提示登陸。
三元的用途還不少,好比結合樣式使用,經過條件判斷來決定使用哪一種樣式,這在實際開發中都很是實用,待你們執行探索。
貳 ❀ 叄 條件邏輯
控制模板是否顯示方面,在vue中有v-if
,在angular中有ng-if
,而在小程序中咱們可使用wx:if
來達到一樣的效果,固然咱們仍是得結合{{}}
使用,好比:
<text wx:if="{{bool}}">我叫聽風是風</text>
注意,wx:if
與咱們以往使用框架中的效果同樣,一旦變量爲false,整個組件不會加載,在小程序解析的wxml模板中你都找不到它,這和組件加載但display:none
是有區別的。
問題來了,假設咱們但願wx:if
不只是控制一個組件,而是好幾個組件的顯示隱藏怎麼辦?這時候咱們能夠結合block
組件使用,看下面的例子:
<block wx:if="{{bool}}"> <text>我叫聽風是風,</text> <text>聽風是風你加點油好很差,真的是!</text> </block>
block
雖然是個組件,但它自己並不會被渲染,只是單純起到容器的做用,好比當bool
爲true能夠看到wxml中並無渲染block
組件,因此你們不用擔憂會不會增長無用組件層級的問題。

實際開發中有這樣一種狀況,好比購物車頁面,若是當前用戶能請求回購物車數據,咱們天然是展現購物車信息,若是請求回來沒數據,咱們確定得給出購物車爲空的友好提示,以angualrjs爲例,我通常是提供2個盒子,大體這麼個意思:
<div class="cart"> <div ng-if="bool"></div> <div ng-if="!bool"></div> </div>
由於angularjs只提供了ng-if狀況,這裏經過 ! 取反值,模擬了if else的狀況。
值得慶幸的是小程序不只提供了wx:if
,還提供了wx:elif
以及wx:else
,因此條件狀況再多,咱們都能應對自如,好比:
<text wx:if="{{num > 0}}"> 大於0 </text> <text wx:elif="{{num < 0}}"> 小於0 </text> <text wx:else> 等於0 </text>
既然談到了wx:if
,用過vue的同窗必定會想問小程序有沒有相似v-show
的指令呢?固然有,咱們能夠給組件添加hidden
屬性來達到v-show
的效果,hidden接受一個Boolean值。wx:if
與hidden
的區別是,wx:if
值爲假時組件直接就不渲染,而hidden
爲真時組件仍是會渲染,只是display爲none。
2020.7.7 更新修改
另外關於hidden
有個小坑,好比下面這個例子:
<text hidden="false">1</text>
你會發現這個組件並不會顯示,而正確的寫法是這樣:
<text hidden="{{false}}">1</text>
出於angularjs以及其它框架的習慣,我一直以爲{{}}
中應該解析變量,沒想到這裏小程序竟然要使用{{}}
包裹一個明確的布爾值。感謝HZz.D.25'11💤指出。
因此站在個人角度,我仍是推薦使用變量表示布爾值,這樣更符合使用習慣,好比下面的例子:
<view hidden="{{bool}}">1</view>
Page({ data: { bool: false }, })
貳 ❀ 肆 列表渲染
在上面的例子中咱們說起購物車有數據以及無數據時的實現場景,若是有數據,咱們其實就得將數據結合模板遍歷出來,在angular中咱們可使用ng-repeat
,vue中有v-for
,很巧,小程序也提供了wx:for
,咱們先來看一個簡單的例子:
<view wx:for="{{array}}"> {{index}}: {{item}} </view>
Page({ data: { array: [1,2,3,4] }, })

不難猜想,這裏的index
與item
就是小程序默認給咱們提供的,當遍歷數組時,當前元素的索引與當前元素自身。
那麼假設數組中的每一個元素都是對象呢?其實仍是同樣的訪問,好比下面這樣:
Page({ data: { array: [{ name:'echo' },{ name:'聽風是風' },{ name:'時間跳躍' }] }, })
<view wx:for="{{array}}"> {{item.name}} </view>
有同窗確定要問了,小程序默認把索引和元素自身命名成了index
與item
,那我本身能不能改個名字呢?能,看下面例子:
<view wx:for="{{array}}" wx:for-index="a" wx:for-item="b"> {{a}}: {{b}} </view>
咱們可使用wx:for-index
與wx:for-item
來自定義index
與item
的名字,想取什麼隨你開心。
上面的例子都是將wx:for
加在了一個組件上面,好比咱們要遍歷購物車數據,那就有購物車圖片,價格,總價,刪除等等對應的組件,這麼多組件怎麼辦?還記得前面提到的無私奉獻的block
組件嗎?沒錯,咱們能夠用它將重要的組件包裹起來,像這樣:
<block wx:for="{{array}}"> <view>{{index}}</view> <view>{{item}}</view> </block>
最後,關於wx:for
性能方法,咱們不得不提wx:key
,這玩意有啥用呢?打個比方,咱們如今有數組[1,2,3,4],小程序將這四項渲染了出來,如今咱們修改重排了數組,變成了[4,3,2,1],若是咱們沒添加wx:key
,小程序會從新渲染,再次遍歷新增四個組件。
而若是咱們在遍歷時添加了wx:key
,小程序會以key做爲一個查找標準,判斷當前已經渲染出來的組件還有沒有用,咱們仔細看數組變化,它只是從新排了序,內容無變化,因此小程序會將以前已經建立好的組件直接再利用進行重排,而不是直接徹底從新渲染一遍,這樣就提高了渲染過程。
再好比[1,2,3,4]變成了[1,2,3,4,5],有key就是在原有基礎上新增一個便可,而不用從新遍歷五個組件,大概就這麼個意思。
OK,咱們解釋了wx:key
做用以後,來講說wx:key
接受什麼作參數,這裏直接引用官方介紹:
wx:key
的值以兩種形式提供:
- 能夠是一個字符串,表明在 for 循環的 array 中 item 的某個屬性,該屬性的值須要是列表中惟一的字符串或數字,且不能動態改變。
- 保留關鍵字 this 表明在 for 循環中的 item 自己,這種表示須要 item 自己是一個惟一的字符串或者數字。
咱們分別對應這兩種值給出兩個例子:
字符串狀況,表示item中的一個屬性,且屬性的值在整個數組中都是獨一無二的數組或字符串:
<view wx:for="{{array}}" wx:key="id" > {{item.name}} </view>
Page({ data: { array: [ {id: 0, name: 'echo'}, {id: 1, name: '聽風是風'}, {id: 2, name: '時間跳躍'}, {id: 3, name: '行星飛行'}, ] } })
this狀況,表示item自身,item應該是獨一無二的數值或者字符串:
<view wx:for="{{array}}" wx:key="*this" > {{item}} </view>
Page({ data: { array: [1, 2, 3, 4] } })
注意,使用過程當中this
前有個星號,雖然不加也沒報錯,但官方是加了因此仍是加吧。
肆 ❀ 總
好了,那麼到這裏,咱們大體介紹完了常見數據綁定的幾種用法,只要有數據,咱們如今能利用各類手段將這些數據渲染到WXML中,這很是棒!
在上文中,咱們在瞭解數據綁定的同時,也知道了第一個事件bindtap
,它屬於點擊事件,那麼在小程序中還有哪些好玩的事件呢?這個問題咱們在下篇教程中揭曉,經過學習事件,讓咱們的小程序頁面更具交互性。
那麼到這裏,本文正式結束。