3.微信小程式-B站:wxml和wxss檔案
WXML
WXML(WeiXin Markup Language)是微信的一套標籤語言,結合基礎元件、事件系統,可以構建出頁面的結構。
(小安娜:好像很厲害的樣子,那基礎元件、事件系統是什麼?感覺更厲害,因為必須結合它們。),基礎元件類似HTML中的標籤,事件系統是JavaScript中的事件,可處理邏輯反應到介面上;wxml只是一個檔案格式,如果沒有元件和事件它沒任何用處,又如果把元件、事件寫在txt文件裡面也沒任何用處,所以沒有誰更厲害,相輔相成的關係。(小安娜:嗦嘎,就好像ap、ad、adc的關係,一起才最強)
用以下一些簡單的例子來看看 WXML 具有什麼能力:
資料繫結
WXML 中的動態資料均來自對應* Page 的 data 物件*
簡單繫結
資料繫結使用 Mustache 語法(雙大括號)將變數包起來,可以作用於以下:
(小安娜:等等,有沒有點誠意,Mustache是什麼都不知道!),Mustache是基於JavaScript實現的模板解析引擎,等等…總之它非常方便和好用。(小安娜:我去,你自己也不知道是什麼吧)
內容
<view> {{ message }} </view>
Page({
data: {
message: 'Hello MINA!'
}
})
顯示結果:
(小安娜:<view>
代表什麼意思,記得HTML中沒這樣的標籤啊?)
元件屬性(需要在雙引號之內)
<view id="item-{{id}}">id="item-{{id}}"</view>
Page({
data: {
id: 0
}
})
顯示結果:
控制屬性(需要在雙引號之內)
<view wx:if="{{condition}}">你看得見我嗎?</view>
Page({
data: {
condition: true
}
})
顯示結果:
(小安娜:我剛剛試了,condition改成false就看不見我了!)
false
就表示條件為假,view元件裡面的內容就不會顯示了。(小安娜:哦明白了,雖然我不想看見你,為了學好小程式還是改成true吧)
關鍵字(需要在雙引號之內)
true
:boolean 型別的 true,代表真值。
false
: boolean 型別的 false,代表假值。
<checkbox checked="{{false}}" />預設沒選中
特別注意:不要直接寫 checked="false"
,這時候"false"
是一個字串,(JavaScript中非0為真、非空位真)轉成boolean
型別後代表真值。
(小安娜:那這個checkbox
是不是和HTML的複選框一樣?),沒錯啦,但checkbox
元件更團結,更多是以組的概念存在,例如我們都會用checkbox-group
包括起所有同類型的checkbox
元件,後面用到自然會明白了。(小安娜:啊啊抓狂了,又多了個checkbox-group
,感覺沒耐心學了),可別這樣想,基礎都是乏味的,可是帶你飛之前要先帶你走,下篇文章我們做案例就會感覺很有意思了。(小安娜:知道啦,那我可以直接看下一篇不^_^),繼續…
所以顯示結果:
運算
可以在 {{}}
內進行簡單的運算,支援的有如下幾種方式:
三元運算
三元運算是:條件 ? 結果1 : 結果2;條件為ture時結果1否則結果2。
<view hidden="{{flag ? true : false}}"> 看得見嗎? </view>
(小安娜:flag
我找了好久沒見你定義啊,你確定不會報錯?),不會的,這種變數即為空變數,(還記得前面提到過非空為真)flag
轉成 boolean
型別後代表false
,也就是表示式最終是這樣的:hidden="{{false}}"
,明白了嗎?(小安娜:阿拉搜,繼續啦)
顯示結果:
算數運算
<view> {{a + b}} + {{c}} + d </view>
Page({
data: {
a: 1,
b: 2,
c: 3
}
})
這次就先不說結果了,小安娜,你來猜猜看結果是什麼?(小安娜:恩~,a=1,b=2,a+b就等於3,c=3,咦~,d沒定義啊?),結果其實是:3 + 3 + d,d不是沒定義,而它本來就是一個文字d,不參與任何計算。(小安娜:我這麼認真回答,你居然這樣坑我!!!)
顯示結果:
字串運算
<view>{{"hello " + name}}</view>
Page({
data:{
name: 'MINA2'
}
})
顯示結果:
資料路徑運算
如果data物件中包含了子物件,例如:
Page({
data: {
object: {
key: 'Hello '
},
array: ['MINA3']
}
})
可以這樣訪問:
<view>{{object.key}} {{array[0]}}</view>
顯示結果:
這個應該沒問題吧?(小安娜:沒問題,就是點操作嘛,一個是JSON物件操作,一個是陣列操作),OK繼續。
組合
也可以在 Mustache 內直接進行組合,構成新的物件或者陣列。
陣列
<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
Page({
data: {
zero: 0
}
})
(小安娜:等等,這裡我看了很久還是理解不了,再細講解下),好,首先我們在data物件中定義zero變數並賦值為0,然後使用view元件的wx:for
屬性表示重複顯示這個元件,wx:for
屬性的值是一個重新構造的陣列,陣列中第一個元素(也就是下標為0)的值來自於data中的zero物件,所以最終是用陣列為[0, 1, 2, 3, 4]
重複渲染元件。(小安娜:哦哦,完~全明白了)
顯示結果:
條件渲染
wx:if
wx:if
我們之前已經用過了,用來判斷是否渲染該元件:
<view wx:if="{{condition}}">你看得見我嗎?</view>
也可以用 wx:elif
和 wx:else
來新增其他判斷:
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
Page({
data: {
length: 10
}
})
介面顯示結果:1
block wx:if
因為 wx:if
是一個控制屬性,需要將它新增到一個標籤上。但是如果我們想一次性判斷多個元件,我們可以使用 <block/>
標籤將多個元件包裝起來,並在block
標籤上用wx:if
控制屬性。
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
這裡的{{true}}
是一個boolean
型別的值,所以最後view1、view2都會顯示。
(小安娜:我記得你說view可以看成div,那block呢,HTML中沒這種控制標籤?),沒錯啦,<block/>
並不是一個元件,它僅是一個包裝元素,不會在頁面中做任何渲染顯示,只接受控制屬性。(小安娜:明白了,block就好像資料夾,不佔用空間,可設定資料夾顯示和隱藏)
列表渲染
wx:for
在元件上使用 wx:for
控制屬性繫結一個數組資料重複渲染該元件。
預設的當前項下標變數名為: index
,陣列當前項的變數名為:item
:(小安娜:不預設是什麼樣啊?)
<view wx:for="{{array}}">
{{index}}:{{item.message}}
</view>
Page({
data: {
array: [{
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>
輸出結果一樣。
block wx:for
類似block wx:if
,也可以將wx:for
用在 <block/>
標籤上,重複渲染多元件塊。例如:
<block wx:for="{{['a', 'b', 'c']}}">
<view> {{index}}:{{item}}</view>
</block>
顯示結果:
wx:key(可以選擇跳過,但,是很重要的重點)
(小安娜:突然有種想打你的衝動,又是重點又可以跳過,下課操場見!!!),冷靜、冷靜,官方文件我看到這時,也是沒理解這是什麼意思,後來就跳過這段了,但是也完成了B站的首頁,(小安娜:哈~,原來是自己傻看不懂,別把我們的智商和你比好吧!),當寫到這時再去多看了一遍(小安娜:絕對不止一遍),把官方例子執行除錯之後,才發現微信官方設計wx:key
的用意,而且是很重要的重點。
如果列表中的專案位置會改變或者有新的專案新增到列表中,為了專案保持自己的屬性和狀態(如 <input/>
的輸入內容,<switch/>
的選中狀態),需要使用wx:key
來指定列表中專案的唯一的識別符號。
wx:key
的值以兩種形式提供:
- 字串;代表在
for
迴圈的array
中item
的某個屬性,該屬性的值是列表中唯一的字串或數字,並且不能動態改變。 - 保留關鍵字;
*this
代表在for
迴圈中的item
本身,這種需要item
本身是唯一的字串或者數字。
是不是完全理解不了什麼意思?(小安娜:我覺得這不是重點,重點是案例你還沒講)
案例1:wx:key
的值是字串
<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
<button bindtap="switch"> 改變順序 </button>
<button bindtap="addToFront"> 新增到前面 </button>
(小安娜:bindtap
是什麼意思呢?),這個是用來繫結事件的,bindtap
是當用戶點選的時候會執行相對於的函式,這個馬上會在事件中詳細講解。
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'},
]
},
// 隨機改變列表專案順序
switch: function(e) {
const length = this.data.objectArray.length
for (let i = 0; i < length; ++i) {
const x = Math.floor(Math.random() * length)
const y = Math.floor(Math.random() * length)
const temp = this.data.objectArray[x]
this.data.objectArray[x] = this.data.objectArray[y]
this.data.objectArray[y] = temp
}
this.setData({
objectArray: this.data.objectArray
})
},
// 新增專案到最前面
addToFront: function(e) {
const length = this.data.objectArray.length
this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
this.setData({
objectArray: this.data.objectArray
})
}
})
(小安娜:天了嚕,一大波程式碼來襲,看不懂了啦),所有函式真可以不用看懂內部實現,只需知道幹什麼用就行(內心的傑爾夫君:其實我知道只有她看不懂,大家照顧照顧她,假裝看不懂)(小安娜:阿丘~誰在說我壞話!)。
顯示結果(①:初始化狀態;②:開啟專案2的開關;③:改變順序後項目2依然是開啟狀態;④:在最前面新增專案6,專案2依然是開啟狀態),這就是wx:key
的作用,它會利用一個唯一值保留該項狀態:
案例2:wx:key
的值是*this
<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch>
<button bindtap="addNumberToFront">新增到前面</button>
Page({
data: {
numberArray: [1, 2, 3, 4]
},
// 新增專案到前面
addNumberToFront: function(e){
this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
this.setData({
numberArray: this.data.numberArray
})
}
})
顯示結果:
模板
WXML提供模板(template),可以在模板中定義程式碼片段,然後在不同的地方呼叫。
使用模板
- 使用name屬性作為模板的名字。然後在
<template/>
內定義程式碼片段。 - 使用 is 屬性,宣告需要的使用的模板,然後將模板所需要的 data 傳入。
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
<!-- 這裡代表把item物件傳入模板 -->
<template is="msgItem" data="{{...item}}"/>
Page({
data: {
item: {
index: 0,
msg: 'this is a template',
time: '2016-09-15'
}
}
})
顯示結果:
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>
顯示結果:
恩~\~,這裡有什麼問題嗎?(小安娜:恩~\~就是呢,不知道模板可以用在什麼地方?),當你網站很多地方都用到同一種結構的時候就可以用了,例如我們要做的B站首頁:
(小安娜:↓↓↓藍色區域第二張圖,不謝)
可以看出綠、紅、藍色區域的結構都一樣,改變的只是內容,這樣的結構就很適合用模板實現。(小安娜:那其他頁面也有這種結構呢?例如B站的直播頁也有這種結構,順便問一下為什麼綠色在最前面XD),像這種需求我們就需要建立單獨的模板檔案,在需要的地方匯入模板檔案就行,接下來就細講這個。
匯入模板
WXML 提供兩種檔案引用方式import
和include
。
帶作用域的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'}}"/>
data="{{text: 'forbar'}}"
表示構造一個物件傳入item.wxml中item模板。
(小安娜:顯示結果是:forbar,對吧?),沒錯啦,厲害了我的小姐姐;還有就是import
有一級作用域的概念,例如:C import B,B import A,在C中可以使用B定義的template,在B中可以使用A定義的template,但是C不能使用A定義的template。
<!-- a.wxml -->
<template name="A">
<text> A template </text>
</template>
<!-- b.wxml -->
<import src="a.wxml"/>
<template name="B">
<text> B template </text>
</template>
<!-- index.wxml -->
<import src="b.wxml"/>
<template is="A"/> <!-- Error! Can not use template when not import A. -->
<template is="B"/>
顯示結果:B template;程式這樣寫編譯會通過,但會在控制檯(Console)報執行時警告(Runtime warn),還請注意。(小安娜:這麼大個坑,那不是debug時很難找出問題?),是啊,的確很難避免,很容易出錯而且找不到問題所在,但顯示結果又不對,所以我們開發的時候要多注意除錯控制檯(Console)輸出的錯誤和異常資訊。(小安娜:開發果然是個細心活,同志們一起加油啦)。
頭部和底部的include
include
可以將目標檔案除了<template/>
的整個程式碼引入,相當於是拷貝到<include />
的位置,比較常用於程式的頭部(header)和底部(footer),例如:
<!-- header.wxml -->
<view>{{header}}</view>
<!-- footer.wxml -->
<view>{{footer}}</view>
<!-- index.wxml -->
<include src="header.wxml"/>
<view> body </view>
<include src="footer.wxml"/>
等同於 === :
<!-- index.wxml -->
<view>{{header}}</view>
<view> body </view>
<view>{{footer}}</view>
// index.js
Page({
data: {
header: "header",
footer: "footer"
}
})
顯示結果:
(小安娜:發現了,它可以直接使用index.js的資料),沒錯,所以這種更適合頭部和底部資料不會隨著頁面不同而改變,而import
更適合定義內容中模板,因為每個頁面的資料結構體是會不一樣的,例如首頁的資料結構可能是:{channels:[music:[],dance:[],live:[]]}
,而在直播頁面中的資料結構可能是:{lives:[]}
,2個頁面資料結構不同,這時候可以用import
把資料重新構造傳入給模板。(小安娜:懵懵懂懂好像明白了),沒關係,後面我們實戰時就會徹底明白了。(小安娜:期待期待~)
事件
事件是檢視層(wxml)到邏輯層(js)的通訊方式,可以繫結在元件上,當觸發事件,就會執行邏輯層中對應的事件處理函式。
事件分類
型別 | 觸發條件 |
---|---|
touchstart | 手指觸控動作開始 |
touchmove | 手指觸控後移動 |
touchcancel | 手指觸控動作被打斷,如來電提醒,彈窗 |
touchend | 手指觸控動作結束 |
tap | 手指觸控後馬上離開 |
longtap | 手指觸控後,超過350ms再離開 |
繫結事件格式為:bind
+ 事件型別(例如:bindtap),我們先來看事件型別的執行順序:
<!-- index.wxml -->
<button
bindtouchstart="ontouchstart"
bindtouchmove="ontouchmove"
bindtouchend="ontouchend"
bindtap="ontap"
bindlongtap="onlongtap">點選我<button/>
Page({
ontouchstart: function() {
console.log( "touchstart" );
},
ontouchmove: function() {
console.log( "touchmove" );
},
ontouchend: function() {
console.log( "touchend" );
},
ontap: function() {
console.log( "tap" );
},
onlongtap: function() {
console.log( "longtap" );
}
})
當點選(<=350ms)的時候,執行順序:
- touchstart
- touchend
- tap
當長按(>350ms)的時候,執行順序:
- touchstart
- longtap
- touchend
- tap
我們發現點選是我們想象中的那樣,但是長按執行一次longtap
還會在執行一次tap
事件,(小安娜:那這就比較坑了,我很喜歡長按一些頭像按鈕,因為會有快捷操作選單),是啊,我知道長按這個操作在Android是很常用的設計,所以我們在小程式裡面儘量避免設計某個元件有長按又有點選事件。(小安娜:因為這個操作太好用了,沒有解決辦法嗎?),可以在data
裡面設定一個判斷長按的變數,當touchstart
的時候設定此變數為false
,當執行longtap
事件的時候設定變數為true
,然後在tap
事件裡面做判斷就行了。
Page({
data: {
islongtap: false
},
ontouchstart: function() {
this.islongtap = false;
console.log( "touchstart" );
},
ontap: function() {
if( this.islongtap ) return ;
console.log( "tap" );
},
onlongtap: function() {
this.islongtap = true;
console.log( "longtap" );
}
})
(小安娜:perfect,運行了下完美解決)
像js的事件一樣,小程式事件也分為冒泡事件和非冒泡事件:
<view id="outter" bindtap="handleTap1">
<view id="middle" bindtap="handleTap2">
<button id="inner" bindtap="handleTap3">
操作按鈕
</button>
</view>
</view>
Page({
handleTap1: function() {
console.log( "handleTap1" );
},
handleTap2: function() {
console.log( "handleTap2" );
},
handleTap3: function() {
console.log( "handleTap3" );
}
})
這是一個常用的結構,一個大的層包含內部很多小層,小層內部有個操作按鈕,當我們點選操作按鈕:
- handleTap3
- handleTap2
- handleTap1
發現所有父元件的點選事件都執行了,這就是冒泡事件:當一個元件上的事件被觸發後,該事件會向父節點傳遞。非冒泡事件就是不會向父節點傳遞。當然這很多時候不是件好事情,怎麼避免呢?
小程式除了提供bind
還提供catch
繫結事件,格式為:catch
+ 事件型別,catch
事件繫結可以阻止向上冒泡。現在在button
上改用catch
試一下:
<view id="outter" bindtap="handleTap1">
<view id="middle" bindtap="handleTap2">
<button id="inner" catchtap="handleTap3">
操作按鈕
</button>
</view>
</view>
輸出結果:handleTap3,達到我們的效果了。(小安娜:我覺得把父元件的繫結事件去掉更好)
事件引數event
當元件觸發事件時,處理函式會收到一個事件物件引數。
Page({
handleTap3: function(event) {
console.log( event );
}
})
控制檯輸出的結果:
{
// 代表事件的型別
"type": "tap",
// 頁面開啟到觸發事件所經過的毫秒數
"timeStamp": 2239,
// 觸發事件的源元件
"target": {
// 事件源元件的id
"id": "inner",
// 距離左方或上層控制元件的位置(官方文件未說明)
"offsetLeft": 0,
// 距離上方或上層控制元件的位置(官方文件未說明)
"offsetTop": 0,
// 事件源元件上由data-開頭的自定義屬性組成的集合
"dataset": {}
},
// 事件繫結的當前元件,資料格式同 target
"currentTarget": {
"id": "inner",
"offsetLeft": 0,
"offsetTop": 0,
"dataset": {}
},
// 額外的資料資訊
"detail": {
"x": 280,
"y": 18
},
// touches 是一個數組,每個元素為一個 Touch 物件(canvas 觸控事件中攜帶的 touches 是 CanvasTouch 陣列)。 表示當前停留在螢幕上的觸控點。
"touches": [
{
// 觸控點的識別符號
"identifier": 0,
// 距離文件左上角的距離,文件的左上角為原點 ,橫向為X軸
"pageX": 280,
// 距離文件左上角的距離,文件的左上角為原點 ,縱向為Y軸
"pageY": 18,
// 距離頁面可顯示區域(螢幕除去導航條)左上角距離,橫向為X軸
"clientX": 280,
// 距離頁面可顯示區域(螢幕除去導航條)左上角距離,縱向為Y軸
"clientY": 18
}
],
// changedTouches 資料格式同 touches。 表示有變化的觸控點,如從無變有(touchstart),位置變化(touchmove),從有變無(touchend、touchcancel)。
"changedTouches": [
{
"identifier": 0,
"pageX": 280,
"pageY": 18,
"clientX": 280,
"clientY": 18
}
]
}
每個引數具體什麼意思,我們放在以後B站專案中去講解,(小安娜:噗~,我好多問題準備問了,現在又憋回去了,聽你講東西真心累),畢竟太多了,每個都講到估計可以寫幾篇文章了,用到什麼再回頭來看看,然後再配合案例這樣最容易理解了。(小安娜:好像也是,總感覺哪裡不對,等等…要是你不用到呢),這個保證不會,因為有我們常用的dataset
,經常會為元件自定義一些引數。(小安娜:姑且相信你)
WXSS
- WXSS(WeiXin Style Sheets)是一套樣式語言,用於描述 WXML 的元件樣式。
- 用來決定 WXML 的元件應該怎麼顯示。
- 具有 CSS 大部分特性。
- 定義在 app.wxss 中的樣式為全域性樣式,可用於任何Page。在 Page 裡的 wxss 檔案中定義的樣式為區域性樣式,只作用在當前頁面,並會覆蓋 app.wxss 中相同的選擇器。
與 CSS 相比增加的特性有:
- 尺寸單位
- 樣式匯入
尺寸單位rpx
rpx(responsive pixel): 可以根據螢幕寬度進行自適應。規定螢幕寬為750rpx。如在 iPhone6 上,螢幕寬度為375px,共有750個物理畫素,則750rpx = 375px = 750物理畫素,1rpx = 0.5px = 1物理畫素。(小安娜:真囉嗦,也就是1px = 2rpx嘛)
裝置 | rpx換算px (螢幕寬度/750) | px換算rpx (750/螢幕寬度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6/6s | 1rpx = 0.5px | 1px = 2rpx |
iPhone6/6s Plus | 1rpx = 0.552px | 1px = 1.81rpx |
所以:我們設計/開發微信小程式時都應該用 iPhone6s 作為視覺稿的標準。(小安娜:所以,看你教程是不是有福利,會給我們發iPhone 6s嗎?)
樣式匯入
使用@import
語句匯入外聯樣式表,@import
後跟樣式表的相對路徑。
/* common.wxss */
.header,
.footer {
padding: 20rpx 0;
text-align: center;
font-size: 50rpx;
}
/* index.wxss */
@import "common.wxss";
.content {
line-height: 50rpx;
}
<view class="header">header</view>
<view class="content" style="color:#e64340;">和小安娜一塊去超市買東西,小安娜:“好想吃泡麵,可是怕上火啊”;我:“那就不要買了”;小安娜:“不行,再去買一罐加多寶吧”;我:...</view>
<view class="footer">footer</view>
這樣就在index.wxss
中匯入了common.wxss
樣式檔案,顯示結果:
(小安娜:你怎麼?不過用加多寶泡泡麵還真挺好吃。喂,快說正事啦,我發現你使用了行內樣式style="color:#e64340;"
),wxss也支援行內樣式,不過儘量避免將靜態的樣式寫入style中,以免影響渲染速度,靜態樣式都應該寫在wxss檔案中。
目前支援的選擇器
選擇器 | 樣例 | 樣例描述 |
---|---|---|
.class | .intro | 選擇所有擁有 class=”intro” 的元件 |
id | firstname | 選擇擁有 id=”firstname” 的元件 |
element | view | 選擇所有 view 元件 |
element, element | view,.header | checkbox 選擇所有文件的 view 元件和所有的 checkbox 元件 |
::after | view::after | 在 view 元件後邊插入內容 |
::before | view::before | 在 view 元件前邊插入內容 |
注意:結果筆者開發試驗,暫時還不支援*選擇器(所有元素),例如我們經常會設定所有元件的box-sizing
屬性來改變測量寬度的起點邊界,從而使規定寬度包括邊框和填充:
* {
box-sizing: border-box;
}
使用之後會發現所有wxss
檔案中的樣式都無效了。(小安娜:那可以怎麼解決呢,難道給每個元件都設定一次?),小哥哥不才,目前還真是每個元件都設定一次,或者這問題官方會很快解決。(小安娜:也是,還是官方靠譜點。)
記得官方文件
瞭解到這,基礎知識終於告一段落了,下一篇開始實戰,開發時更多元件知識請參考官方文件。
寫了這麼多口好乾,我需要倒杯水喝,等等我。(小安娜:去吧去吧),「滴答、滴答,過去5分鐘…10分鐘…」(小安娜:喂喂,10分鐘了,你是喝一桶水嗎?),(遠處的聲音:quatary kill!WO CAO,要超神了),(小安娜:我去,喝個水時間去開黑了,快滾回來,馬上到我的提問環節了!),都怪你了,一開始就說什麼ap、ad、adc,搞的我熱血沸騰的,馬上來了。
小安娜有問題
WXML是什麼?
傑爾夫君:WXML(WeiXin Markup Language)是一套標籤語言,結合基礎元件、事件系統,可以構建出頁面的結構。和HTML相似。
WXML元件怎麼繫結資料?
**傑爾夫君:**WXML中的動態資料均來自對應 Page 的 data。資料繫結使用 Mustache 語法(雙大括號)將變數包起來。例如:
Page({
data: {
message: 'Hello MINA!'
}
})
<!-- 繫結Page中的data.message -->
<view> {{ message }} </view>
什麼是Mustache?
WXML中怎麼使用條件判斷?
傑爾夫君:在框架中,我們用 wx:if="{{condition}}"
來判斷是否需要渲染該程式碼塊:
<view wx:if="{{condition}}"> True </view>
也可以用 wx:elif
和 wx:else
:
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
如果想一次性判斷多個元件標籤,我們可以使用一個 <block/>
標籤將多個元件包裝起來:
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
WXML怎麼迴圈列表?
傑爾夫君:在元件上使用wx:for
屬性繫結一個數組,即可使用陣列中的資料重複渲染該元件,預設當前的下標變數名為index
,當前項的變數名為item
。用wx:for-index
指定當前下標的變數名,用wx:for-item
指定當前元素的變數名;
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>
等等,怎麼感覺你從頭到尾都有問題啊,感覺沒學過一樣?(小安娜:沒辦法啦,這次講太多了,本小姐記憶不太好,都不記得學了什麼),好吧好吧,也正好總結一下,繼續你的問題。(小安娜:你別打斷啊!)
WXML怎麼使用模板?
傑爾夫君:用<template/>
定義模板,指定name
屬性為模板的名字,用is
屬性指定使用模板的名稱,然後將模板所需要的data
傳入,如:
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
<!-- 引數傳入Page中的data.item -->
<template is="msgItem" data="{{...item}}"/>
Page({
data: {
item: {
index: 0,
msg: 'this is a template',
time: '2016-09-15'
}
}
})
也可以把模板定義在單獨檔案中,通過import
或include
引入。
<!-- import -->
<!-- item.wxml -->
<template name="item">
<text>{{text}}</text>
</template>
<!-- index.wxml -->
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
<!-- include -->
<!-- header.wxml -->
<view> header