這是微信小程序踩坑系列的第三篇,想要了解更多關於微信小程序開發的那些事,歡迎關注個人《微信小程序》專欄。javascript
開發微信小程序離不開「頁面渲染」,對於初學者來講很難理解小程序裏的「頁面渲染」是什麼、怎麼用?
而學過 vue 的同窗來講,這個就比較熟悉了,實際上就是數據綁定頁面渲染。
那麼關於頁面渲染最重要的是列表渲染和條件渲染這兩塊,先來看看幾個簡單的例子。html
下面是個「列表渲染」的例子:vue
<view wx:for="{{array}}"> {{index}}: {{item.message}} </view>
Page({ data: { array: [{ message: 'foo', }, { message: 'bar' }] } })
上面的例子能夠看出,默認數組的當前項的下標變量名默認爲 index,數組當前項的變量名默認爲 item。固然,使用 wx:for-item 能夠指定數組當前元素的變量名,使用 wx:for-index 能夠指定數組當前下標的變量名,以下:java
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> {{idx}}: {{itemName.message}} </view>
下面是個「條件渲染」的例子:node
<view wx:if="{{condition}}">True</view>
Page({ data: { condition: true } })
上面的例子說明,當 condition 爲真時,頁面渲染上面的 view 標籤。固然也能夠用 wx:elif 和 wx:else 來添加一個 else 塊,以下:小程序
<view wx:if="{{length > 5}}">1</view> <view wx:elif="{{length > 2}}">2</view> <view wx:else>3</view>
下面接入正題,探索文章題目的疑問segmentfault
其實初次看 官方文檔 可能會對 wx:key 有點懵,官方解釋是這樣的:微信小程序
根據我多年看文檔經驗,通常我看不懂的能夠忽略不重要的文字,只需關注重點,例如上圖的文字加粗部分,所以,一開始我選擇不寫 wx:key 這個屬性。然而在開發過程當中寫多了列表渲染(而沒有加 wx:key)以後,控制檯會報不少的 wx:key 的警告,對於有點代碼潔癖的我看起來很不爽,但又苦於不清楚 wx:key 的真正做用,因而自創了一個解決辦法,那就是在每一個列表渲染後面加上 wx:key="{{index}}",相似下面這樣:數組
<view wx:for="{{array}}" wx:key="{{index}}"> {{item}} </view>
因而我驚奇地發現警告通通不見了,也沒有其餘負面影響,因而我就這樣用了大半年。
然而,半年前我作的一個項目裏面有個列表渲染須要試試獲取用戶頭像和暱稱,因而我以前的作法無論用了,每次獲取到的用戶信息跟當前內容不對應,而且會發生錯亂。因而我從新理解了一遍 wx:key,結合下面的例子,我彷佛明白了:微信
<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
Page({ data: { objectArray: [ {id: 5, unique: 'unique_5'}, {id: 4, unique: 'unique_4'}, {id: 3, unique: 'unique_3'}, {id: 2, unique: 'unique_2'}, {id: 1, unique: 'unique_1'}, {id: 0, unique: 'unique_0'}, ] } })
其實,wx:key 是用來綁定當前列表中的項目特徵的,也就是說,若是列表是動態更新的,那麼 wx:key 的做用是保持原有項目的整個狀態不變。
結合上面的例子,咱們能夠知道,對於列表數組是個對象數組,那麼 wx:key 屬性直接寫對應的惟一的屬性名就能夠了,好比上面的 wx:key="unique", 或者 wx:key="id" 也是能夠的,只要保持屬性是惟一值就好了,有點相似頁面標籤裏面的 id 屬性在頁面是惟一的。
對於列表數組是個基本類型數組,那麼直接寫 wx:key="*this" 就能夠了,以下:
<block wx:for="{{[1, 2, 3]}}" wx:key="*this"> <view>{{index}}:</view> <view>{{item}}</view> </block>
其實咱們用條件渲染更多地在用 wx:if 而不是 hidden,由於前者能夠拓展,後者缺少必定的邏輯。然而他們到底有什麼區別呢?
官方文檔 是這樣描述的:
上圖中,咱們大概能夠了解到,若是須要頻繁切換狀態,用 hidden,不然用 wx:if。
也就是說,wx:if 可以實時建立渲染組件或銷燬組件,並且當他爲真時纔會建立,初始爲假時什麼也不作,由真變爲假時則進行銷燬。因此頻繁切換他是一個比較耗性能舉動。而 hidden 則表明頁面初始渲染時就會把該組件渲染在頁面上,值的真假只是控制其顯示隱藏罷了。頁面不銷燬,則該組件也不會被銷燬。
明白了這一點,你會發現,從咱們開發者的角度來講,靈活使用這兩個條件判斷會事半功倍。
下面列舉幾種使用場景給開發者參考:
<view class="load-event" hidden="{{!isAdd}}">加載中……</view> <view class="load-event" hidden="{{!isAdded && isMore}}">沒有更多了</view>
上面代碼是一個上拉加載動畫顯示與隱藏組件,能夠看到用的是 hidden,由於他是一個須要頻繁切換的組件。
<block wx:if="{{node.name === 'p'}}"> <view class="{{node.attrs.class}}" data-index="{{index}}" bindtap="toText"> <text selectable="true">{{node.children[0].text}}</text> </view> </block> <block wx:if="{{node.name === 'img'}}"> <image class="{{node.attrs.class}}" src="{{node.attrs.src}}"></image> </block> <block wx:if="{{node.name === 'video'}}"> <video class="{{node.attrs.class}}" src="{{node.attrs.src}}"></video> </block>
上面代碼展現的是渲染文字仍是圖片或者是視頻,只展現其中的一個那麼用 wx:if 最佳。
下面是一個自定義 input 組件:
<view wx:if="{{isInput}}" class="show-input"> <view class="input-item"> <input class="item-input" bindconfirm="onSend" bindinput="inputHandle" bindblur="hideInput"></input> <view class="send-btn" catchtap="onSend">發送</view> </view> </view>
其功能是點擊評論按鈕能實時顯示輸入框,不然隱藏。這裏爲何用 wx:if 呢?由於我但願它顯示時是新的 input 組件,不是以前渲染好的,這樣若是我剛輸入完文字,再次評論不會出現上一次的文字殘留。
一、 <block> 這個元素在列表和條件渲染上是很好用的,不過要注意不要在這個標籤上綁定其餘屬性,好比 data- 或者綁定事件 bindtap。下面是一個反例:
<block wx:if="{{true}}" data-id="1" bindtap="tapName"> <view>view1</view> <view>view2</view> </block>
上面的代碼裏,在 js 中定義綁定事件後,你會發現不會執行。緣由就在 <block> 元素在渲染頁面後並不會存在,他不是個組件,不會渲染在頁面樹節點裏面,因此在他上面綁定的事件或者屬性也不會有效。
二、 當 wx:for 的值爲字符串時,會將字符串解析成字符串數組;另外,花括號和引號之間若是有空格,將最終被解析成爲字符串,請看下面的例子:
<view wx:for="array"> {{item}} </view>
等同於
<view wx:for="{{['a','r','r','a','y']}}"> {{item}} </view>
<view wx:for="{{[1,2,3]}} "> {{item}} </view>
等同於
<view wx:for="{{[1,2,3] + ' '}}"> {{item}} </view>
(完)
本文做者 Thinker本文若有錯誤之處,請留言,我會及時更正
以爲對您有幫助的話就點個贊或收藏吧!
歡迎轉載或分享,轉載時請註明出處