從零開始的微信小程序入門教程(三),有趣且好玩的數據綁定


壹 ❀ 引

我在從零開始的微信小程序入門教程(二),初識WXML與WXSS一文中簡單介紹了小程序組件與小程序樣式相關概念,在了解這兩者之后,其實我們已經可以搭建出簡單的靜態頁面,與書寫HTML頁面一樣,小程序頁面也只能通過多寫多練提升。在構建完頁面后就出現了一個問題,我們該如何獲取組件元素讓數據與之關聯呢?

在網頁開發中,我們同樣使用JS操作DOM,包括數據渲染,事件監聽等,比如我現在要通過點擊一個按鈕后,替換段落中的本文信息,使用JS可以這么做:

<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.wxmlindex.js中添加如下代碼:

<text>{{myName}}</text>
<button bindtap="setName">點我點我</button>
const app = getApp()

Page({
  data: {
    myName:'我是誰?'
  },
  setName() {
    this.setData({ myName: "噴火龍" })
  }
})

接下來我們解釋下小程序數據綁定到底怎么玩,以及其它幾種常見的數據交互方式。

貳 ❀ 數據交互

貳 ❀ 壹 數據綁定{{}}

熟悉vue等相關框架的同學對於上述例子一定十分熟悉,對於第一次了解這種用法的同學也不用擔心,並不復雜,我們來解釋下到底什么是意思。

首先看WXML,小程序使用{{}}表達式來綁定解析JS文件中定義的變量,而在JS文件的data對象中一般用於定義小程序初始化所需數據,比如例子中的變量myName有一個初始值。

Page({
  data: {
    /* 頁面初始數據寫在這*/
  }
})

接下來就是如何通過點擊事件讓myName發生變化,在組件button上我們通過點擊事件bindtap綁定了一個setName方法,注意,這個方法同樣定義在JS文件Page對象中,與data對象同級,以往我們綁定方法一般會給方法名后帶括號,小程序的方法綁定並沒有括號,比如上面的bindtap="setName"

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:ifhidden的區別是,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]
  },
})

不難猜測,這里的indexitem就是小程序默認給我們提供的,當遍歷數組時,當前元素的索引與當前元素自身。

那么假設數組中的每個元素都是對象呢?其實還是一樣的訪問,比如下面這樣:

Page({
  data: {
    array: [{
      name:'echo'
    },{
      name:'聽風是風'
    },{
      name:'時間跳躍'
    }]
  },
})
<view wx:for="{{array}}">
  {{item.name}}
</view>

有同學肯定要問了,小程序默認把索引和元素自身命名成了indexitem,那我自己能不能改個名字呢?能,看下面例子:

<view wx:for="{{array}}" wx:for-index="a" wx:for-item="b">
  {{a}}: {{b}}
</view>

我們可以使用wx:for-indexwx:for-item來自定義indexitem的名字,想取什么隨你開心。

上面的例子都是將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 的值以兩種形式提供:

  1. 可以是一個字符串,代表在 for 循環的 array 中 item 的某個屬性,該屬性的值需要是列表中唯一的字符串或數字,且不能動態改變。
  2. 保留關鍵字 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,它屬於點擊事件,那么在小程序中還有哪些好玩的事件呢?這個問題我們在下篇教程中揭曉,通過學習事件,讓我們的小程序頁面更具交互性。

那么到這里,本文正式結束。

教程第四篇已更新:從零開始的微信小程序入門教程(四),理解小程序事件與冒泡機制


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2024 CODEPRJ.COM