|
導讀微信小程序,簡稱小程序,英文名Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應用。小程序是一種不用下載就能使用的應用,也是一... 微信小程序,簡稱小程序,英文名Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應用。小程序是一種不用下載就能使用的應用,也是一項門檻非常高的創新,經過將近兩年的發展,已經構造了新的小程序開發環境和開發者生態。 WXMLWXML(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 id="item-{{id}}">id="item-{{id}}"</view>Page({
data: {
id: 0
}
})顯示結果:
顯示結果 控制屬性(需要在雙引號之內)<view wx:if="{{condition}}">你看得見我嗎?</view>Page({
data: {
condition: true
}
})顯示結果:
顯示結果 (小安娜:我剛剛試了,condition改成false就看不見我了!),是的,改成 關鍵字(需要在雙引號之內)
<checkbox checked="{{false}}" />默認沒選中特別注意:不要直接寫 (小安娜:那這個 所以顯示結果:
顯示結果 運算可以在 三元運算三元運算是:條件 ? 結果1 : 結果2;條件為ture時結果1否則結果2。 <view hidden="{{flag ? true : false}}"> 看得見嗎? </view>(小安娜: 顯示結果:
顯示結果 算數運算<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:if
<view wx:if="{{condition}}">你看得見我嗎?</view>也可以用 <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因為 <block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>這里的 (小安娜:我記得你說view可以看成p,那block呢,HTML中沒這種控制標簽?),沒錯啦, 列表渲染wx:for在組件上使用 默認的當前項下標變量名為: <view wx:for="{{array}}">
{{index}}:{{item.message}}
</view>Page({
data: {
array: [{
message: 'foo',
}, {
message: 'bar'
}]
}
})顯示結果:
顯示結果 不使用默認可以使用 <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>輸出結果一樣。 block wx:for類似 <block wx:for="{{['a', 'b', 'c']}}">
<view> {{index}}:{{item}}</view>
</block>顯示結果:
顯示結果 wx:key(可以選擇跳過,但,是很重要的重點)(小安娜:突然有種想打你的沖動,又是重點又可以跳過,下課操場見!!!),冷靜、冷靜,官方文檔我看到這時,也是沒理解這是什么意思,后來就跳過這段了,但是也完成了B站的首頁,(小安娜:哈~,原來是自己傻看不懂,別把我們的智商和你比好吧!),當寫到這時再去多看了一遍(小安娜:絕對不止一遍),把官方例子運行調試之后,才發現微信官方設計 如果列表中的項目位置會改變或者有新的項目添加到列表中,為了項目保持自己的屬性和狀態(如
是不是完全理解不了什么意思?(小安娜:我覺得這不是重點,重點是案例你還沒講) 案例1: <switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
<button bindtap="switch"> 改變順序 </button>
<button bindtap="addToFront"> 添加到前面 </button>(小安娜: 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依然是打開狀態),這就是
顯示結果 案例2: <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),可以在模板中定義代碼片段,然后在不同的地方調用。 使用模板
<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站首頁 可以看出綠、紅、藍色區域的結構都一樣,改變的只是內容,這樣的結構就很適合用模板實現。(小安娜:那其他頁面也有這種結構呢?例如B站的直播頁也有這種結構,順便問一下為什么綠色在最前面XD),像這種需求我們就需要創建單獨的模板文件,在需要的地方導入模板文件就行,接下來就細講這個。 導入模板WXML 提供兩種文件引用方式 帶作用域的import
<!-- item.wxml -->
<template name="item">
<text>{{text}}</text>
</template>在 index.wxml 中引用了 item.wxml,就可以使用item模板: <import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
(小安娜:顯示結果是:forbar,對吧?),沒錯啦,厲害了我的小姐姐;還有就是 <!-- 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
<!-- 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的數據),沒錯,所以這種更適合頭部和底部數據不會隨著頁面不同而改變,而 事件事件是視圖層(wxml)到邏輯層(js)的通訊方式,可以綁定在組件上,當觸發事件,就會執行邏輯層中對應的事件處理函數。 事件分類
綁定事件格式為: <!-- 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)的時候,執行順序:
當長按(>350ms)的時候,執行順序:
我們發現點擊是我們想象中的那樣,但是長按執行一次 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" );
}
})這是一個常用的結構,一個大的層包含內部很多小層,小層內部有個操作按鈕,當我們點擊操作按鈕:
發現所有父組件的點擊事件都執行了,這就是冒泡事件:當一個組件上的事件被觸發后,該事件會向父節點傳遞。非冒泡事件就是不會向父節點傳遞。當然這很多時候不是件好事情,怎么避免呢? 小程序除了提供 <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站項目中去講解,(小安娜:噗~,我好多問題準備問了,現在又憋回去了,聽你講東西真心累),畢竟太多了,每個都講到估計可以寫幾篇文章了,用到什么再回頭來看看,然后再配合案例這樣最容易理解了。(小安娜:好像也是,總感覺哪里不對,等等...要是你不用到呢),這個保證不會,因為有我們常用的 WXSS
與 CSS 相比增加的特性有:
尺寸單位rpxrpx(responsive pixel): 可以根據屏幕寬度進行自適應。規定屏幕寬為750rpx。如在 iPhone6 上,屏幕寬度為375px,共有750個物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。(小安娜:真啰嗦,也就是1px = 2rpx嘛)
所以:我們設計/開發微信小程序時都應該用 iPhone6s 作為視覺稿的標準。(小安娜:所以,看你教程是不是有福利,會給我們發iPhone 6s嗎?) 樣式導入使用 /* 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> 這樣就在
顯示結果 (小安娜:你怎么?不過用加多寶泡泡面還真挺好吃。喂,快說正事啦,我發現你使用了行內樣式 目前支持的選擇器
注意:結果筆者開發試驗,暫時還不支持*選擇器(所有元素),例如我們經常會設置所有組件的 * {
box-sizing: border-box;
}使用之后會發現所有 記得官方文檔了解到這,基礎知識終于告一段落了,下一篇開始實戰,開發時更多組件知識請參考官方文檔。
小安娜有問題WXML是什么?杰爾夫君:WXML(WeiXin Markup Language)是一套標簽語言,結合基礎組件、事件系統,可以構建出頁面的結構。和HTML相似。 WXML組件怎么綁定數據?杰爾夫君:WXML中的動態數據均來自對應 Page 的 data。數據綁定使用 Mustache 語法(雙大括號)將變量包起來。例如: Page({
data: {
message: 'Hello MINA!'
}
})<!-- 綁定Page中的data.message -->
<view> {{ message }} </view>什么是Mustache?杰爾夫君:Mustache 是一個 logic-less (輕邏輯)模板解析引擎。在小程序里主要關注小程序的語法。詳細了解前往:www.open-open.com/lib/view/open1416792564461.html WXML中怎么使用條件判斷?杰爾夫君:在框架中,我們用 <view wx:if="{{condition}}"> True </view>也可以用 <view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>如果想一次性判斷多個組件標簽,我們可以使用一個 <block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>WXML怎么循環列表?杰爾夫君:在組件上使用 <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>等等,怎么感覺你從頭到尾都有問題啊,感覺沒學過一樣?(小安娜:沒辦法啦,這次講太多了,本小姐記憶不太好,都不記得學了什么),好吧好吧,也正好總結一下,繼續你的問題。(小安娜:你別打斷啊!) WXML怎么使用模板?杰爾夫君:用 <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 -->
<!-- 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 </view> <!-- footer.wxml --> <view> footer </view> <!-- index.wxml --> <include src="header.wxml"/> <view> body </view> <include src="footer.wxml"/>
WXML中怎么使用事件?杰爾夫君:使用 什么是WXSS?杰爾夫君:WXSS(WeiXin Style Sheets)是一套樣式語言,用于描述 WXML 的組件樣式。WXSS 具有 CSS 大部分特性。 同時為了更適合開發微信小程序,對 CSS 進行了擴充以及修改了:尺寸單位、樣式導入。 尺寸單位rpx(responsive pixel): 可以根據屏幕寬度進行自適應。規定屏幕寬為750rpx。以iPhone6為例:1rpx = 0.5px,1px = 2rpx。 樣式導入使用 @import "common.wxss";
.middle-p {
padding:15px;
}以上就是微信小程序中wxml和wxss文件詳解的詳細內容,更多請關注php中文網其它相關文章! 小程序是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或者搜一下即可打開應用。 |
溫馨提示:喜歡本站的話,請收藏一下本站!