微信小程序就是一個(gè)類似 RN(React Native)的輪子,可以快速開發(fā),有一定的適用場景,但是也有其局限性。
注:該結(jié)論是基于微信小程序的示例代碼做的解讀,可能存在謬誤。
早先,看到很多「權(quán)威人士」說小程序是 Hybrid 模式。一度懷疑自己之前判斷的準(zhǔn)確性,擔(dān)心誤導(dǎo)別人,所以額外備注可能存在謬誤。
目前來看,這篇文章的判斷比大部分博客文章的判斷都準(zhǔn)確。
簡單總結(jié)下觀點(diǎn):
微信小程序是原生應(yīng)用,是 React Native 和 Weex 類似的模式。
微信小程序的生態(tài)除了官方提供的組件和 API,幾乎沒有其他的組件。所以部分看上去「復(fù)雜」的功能,開發(fā)起來真的很復(fù)雜。
微信小程序只能在微信中運(yùn)行。
由于微信的限制,微信小程序的應(yīng)用場景極度有限。
大家想知道微信小程序能干什么?對比服務(wù)號就知道了。比如訂票、航旅信息、ToDo List、天氣日歷、星座、理財(cái)、實(shí)時(shí)點(diǎn)菜系統(tǒng)等,核心是低頻但重要的需求。
而且,微信不允許分享(導(dǎo)流),不允許鏈接(導(dǎo)流或廣告),所以想要靠微信朋友圈爆發(fā)的小機(jī)靈被徹底被澆滅了,媒體也不適合微信小程序。
此外,不得不吐槽一下微信和微信小程序:
1. 微信小程序的官方文檔寫得不完善,很多方面沒有覆蓋
如何定義一個(gè)組件。
無法使用 LESS 或者 SASS 之類的預(yù)編譯。
WXML 沒得到主流編輯器的支持,導(dǎo)致開發(fā)速度偏慢。
2. 微信小程序的開發(fā)工具極不穩(wěn)定
和 Shadowsocks 等 VPN 沖突。
經(jīng)常無故卡死。
開發(fā)工具和真機(jī)表現(xiàn)偶爾會有差異。
有時(shí)候代碼無故不生效,需要重啟才行。
沒有類似 HMR 的機(jī)制導(dǎo)致經(jīng)常刷新。
調(diào)試工具不好用等等。
3. 微信小程序的生態(tài)和問答社區(qū)幾乎為零
微信的生態(tài)為零,導(dǎo)致部分功能開發(fā)起來吃力,比如解析富文本。
微信的問答社區(qū)就更差了,遇到問題全靠猜,實(shí)在找不到辦法就重啟。
4. 微信小程序的應(yīng)用場景太受限
這個(gè)和微信的一貫保守風(fēng)格很像,或許以后會慢慢放開,慢慢期待吧。
以上觀點(diǎn)是站在一個(gè)普通開發(fā)者的角度,對微信小程序的看法。相反,從微信角度出發(fā),某些限制和規(guī)范的確很有必要。
希望大家客觀對待微信小程序。
而本文主要針對微信小程序的示例代碼進(jìn)行分析,想告訴大家以下幾件事:
微信小程序到底提供了什么?
開發(fā)微信小程序方便么?
微信小程序的具體適用場景?
最后,還自作主張地說了點(diǎn)對于微信小程序的個(gè)人觀點(diǎn)。
微信小程序都提供了什么?
微信小程序主要為我們提供了兩部分東西:底層 API 、組件。
不僅如此,微信小程序還引入新的文件格式。
1. 引入了新的文件格式
微信小程序并不是傳統(tǒng)意義的 HTML 5 頁面,微信定義了新的文件格式,然后對這些文件做編譯解析。
所以,微信小程序是原生應(yīng)用!是基于微信的原生應(yīng)用!微信正式嘗試做一個(gè) OS(操作系統(tǒng))!
微信小程序組件
上圖是一個(gè) wx-action-sheet 組件,文件應(yīng)用了新的后綴。
其中,WXML 功能和 HTML 類似,WXSS 功能和 CSS 類似,JS 包含組件邏輯。這點(diǎn)是不是和 RN/Weex 很像?
2. 微信提供了一套基礎(chǔ)組件庫
微信為微信小程序提供了一套基礎(chǔ)組件庫,可以滿足開發(fā)的基礎(chǔ)開發(fā)需求,從而實(shí)現(xiàn)簡單的快速開發(fā)。
至于這些基礎(chǔ)組件支持多大程度的自定義,以及能否滿足實(shí)際項(xiàng)目的需求,就留給后續(xù)開發(fā)者去體驗(yàn)吧。
基礎(chǔ)組件庫主要分為四類:
控件(controller)主要包括:action-sheet / button / searchbar / modal / / drawer
表單(form)主要包括:checkbox / radio / form / or / switch / slider /input / label / picker
媒體(media)主要包括:image / audio / video
視圖(view)主要包括:progress / toast / scroll-view / text / view / mask / icon/ spinner / swiper / slide-tab
嗯,不用介紹大家也都知道這些組件大概是什么功能了,幾乎是每個(gè) UI 組件庫都必備的。
以后大家應(yīng)該都基于這個(gè)組件庫去開發(fā)具體的產(chǎn)品。
和 RN/Weex 不同的是,微信小程序多半只能基于微信提供的組件進(jìn)行個(gè)性化封裝,而不能基于系統(tǒng)組件進(jìn)行個(gè)性化封裝。
原因很簡單,因?yàn)槲⑿啪褪且粋€(gè)「系統(tǒng)」。
微信是一個(gè)「系統(tǒng)」
我們挑一個(gè)稍微復(fù)雜的 picker 組件示例來分析分析:
// wx-picker.wxml文件 <view class="page"> <view class="page__hd"> <text class="page__title">picker</text> <text class="page__desc">選擇器</text> </view> <view class="page__bd"> <view class="section"> <view class="section__title">地區(qū)選擇器</view> <picker bindchange="bindPickerChange" value="{{index}}" range="{{array}}"> <view class="picker"> 當(dāng)前選擇:{{array[index]}} </view> </picker> </view> <view class="section"> <view class="section__title">日期選擇器</view> <picker mode="date" value="{{date}}" start="2015-09-01" end="2017-09-01" bindchange="bindDateChange"> <view class="picker"> 當(dāng)前選擇: {{date}} </view> </picker> </view> </view> </view>
是的,所有的標(biāo)簽都是自定義標(biāo)簽,進(jìn)一步佐證了微信小程序是原生應(yīng)用。組件使用很簡單,所以很適合快速開發(fā)。
// wx-picker 文件
Page({
data: {
array:["中國","美國","巴西","日本"],
index:0,
date:"2016-09-01"
},
bindPickerChange: (e) {
console.log('picker發(fā)送選擇改變,攜帶值為', e.detail.value)
this.setData({
index: e.detail.value
})
},
bindDateChange:(e){
this.setData({
date:e.detail.value
})
},
bindTimeChange:(e){
this.setData({
time:e.detail.time
})
}
})
也很清晰,通過 this.setData 來設(shè)置屬性,實(shí)現(xiàn) action-sheet 的顯示與隱藏切換。React 的感覺,連 API 都很像。
// wx-picker.wxss
.picker{
padding: 13px;
background-color: #FFFFFF;
}
可以重新設(shè)置微信小程序的組件樣式,和 CSS 很相似,輕量簡潔。
3. 底層 API
沒有提供底層 API 的基礎(chǔ)組件庫都是流氓庫,有了底層 API 才能開發(fā)真正的原生應(yīng)用,才能做更多豐富的功能。
其中底層 API 包括:
animation / backgronud-audio / canvas / download-file / file / get-location / get-network-type / get-system-info / get-user-info / image / login / navigation-bar-loading / / on-accelerometer-change / on-compass-change / open-location /pull-down-refresh / request / request-payment / set-navigation-bar-title / storage/ upload-file / voice / web-socket
從名字也能看出個(gè)大概,小程序提供了比較完整的 API,能夠開發(fā)更豐富的功能和程序。
我們?nèi)匀惶粢粋€(gè)稍微復(fù)雜點(diǎn)的、圖片相關(guān)的 API 使用示例來分析分析:
// image.wxml文件 <import src="../common/header.wxml" /> <import src="../common/footer.wxml" /> <view class="container"> <template is="header" data="{{title: 'choose/previewImage'}}"/> <view class="page-body"> <view class="page-body-wrapper"> <form bindsubmit="openLocation"> <view class="page-body-form"> <picker range="{{sourceType}}" bindchange="sourceTypeChange" value="{{sourceTypeIndex}}"> <view class="page-body-form-picker"> <view class="page-body-form-picker-key"> 圖片來源 </view> <view class="page-body-form-picker-value"> {{sourceType[sourceTypeIndex]}} </view> </view> </picker> <picker range="{{sizeType}}" bindchange="sizeTypeChange" value="{{sizeTypeIndex}}"> <view class="page-body-form-picker"> <view class="page-body-form-picker-key"> 圖片質(zhì)量 </view> <view class="page-body-form-picker-value"> {{sizeType[sizeTypeIndex]}} </view> </view> </picker> <picker range="{{count}}" bindchange="countChange" value="{{countIndex}}"> <view class="page-body-form-picker" style="border-bottom: none;"> <view class="page-body-form-picker-key"> 數(shù)量限制 </view> <view class="page-body-form-picker-value"> {{count[countIndex]}} </view> </view> </picker> </view> <view class="images-wrapper"> <text class="images-text">請選擇圖片</text> <view class="images-list"> <block wx:for-items="{{imageList}}" wx:for-item="image"> <image src="{{image}}" class="images-image" data-src="{{image}}" bindtap="previewImage"></image> </block> <image src="/image/plus.png" class="images-image images-image-plus" bindtap="chooseImage"></image> </view> </view> </form> </view> </view> <template is="footer" /> </view>
簡單清晰 WXML,居然讓選擇圖片及及預(yù)覽實(shí)現(xiàn)起來這么簡單。并且,可以通過簡單的 template 語法來引入其他 WXML 文件。
// image 文件
var sourceType = [
['camera'],
['album'],
['camera', 'album'] ]
var sizeType = [ ['compressed'],
['original'],
['compressed', 'original'] ]
Page({
data: {
sourceTypeIndex: 0,
sourceType: ['拍照', '相冊', '拍照或相冊'],
sizeTypeIndex: 0,
sizeType: ['壓縮', '原圖', '壓縮或原圖'],
countIndex: 0,
count: [1, 2, 3, 4, 5, 6, 7, 8, 9]
},
sourceTypeChange: (e) {
this.setData({
sourceTypeIndex: e.detail.value
})
},
sizeTypeChange: (e) {
this.setData({
sizeTypeIndex: e.detail.value
})
},
countChange: (e) {
this.setData({
countIndex: e.detail.value
})
},
chooseImage: () {
var that = this
wx.chooseImage({
sourceType: sourceType[this.data.sourceTypeIndex],
sizeType: sizeType[this.data.sizeTypeIndex],
count: this.data.count[this.data.countIndex],
success: (res) {
console.log(res)
that.setData({
imageList: res.tempFilePaths
})
}
})
},
previewImage: (e) {
var current = e.target.dataset.src
wx.previewImage({
current: current,
urls: this.data.imageList
})
}
})
因?yàn)槲⑿艑@個(gè) API 已經(jīng)封裝得很好了,所以使用起來只需要傳入幾個(gè)參數(shù),綁定一下回調(diào)函數(shù)即可。
// image.css 文件
.images-wrapper {
padding: 20rpx;
background-color: #fff;
margin-top: 20rpx;
}
.images-wrapper-text {
font-size: 28rpx;
}
.images-list {
display: flex;
margin-top: 20rpx;
flex-wrap: wrap;
}
.images-image {
width: 150rpx;
height: 150rpx;
margin: 10rpx;
}
.images-image-plus {
border: 1px solid #999;
}
同樣,樣式表語法近似 CSS,從上面的 rpx 單位可以看出,這不是真正的 CSS,我猜測是 CSS 的子集,類似 RN。
開發(fā)微信小程序方便么?
1. 微信小程序的開發(fā)目錄結(jié)構(gòu)
WX 的開發(fā)目錄結(jié)構(gòu)也很清晰簡單。
WX 目錄結(jié)構(gòu)
入口文件就是最外層的 appappon,app.wxss。
app 提供了入口文件的一些初始化和綁定。
appon 提供了項(xiàng)目的結(jié)構(gòu)和一些項(xiàng)目配置,微信之所以采用 appon 的模式,聲明項(xiàng)目需要加載的頁面和組件,應(yīng)該是為了方便實(shí)現(xiàn)云端編譯打包然后下發(fā)到微信吧。
app.wxss 就是樣式啦。
page 目錄放你需要實(shí)現(xiàn)具體功能的頁面。
util 存放項(xiàng)目需要用到的一些工具函數(shù)。
// appon
{
"pages": [
"page/component/component-pages/wx-picker/wx-picker",
"page/API/image/image"
],
"window": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "小程序演示",
"navigationBarBackgroundColor": "#fbf9fe",
"backgroundColor": "#fbf9fe"
},
"tabBar": {
"color": "#dddddd",
"edColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "page/component/index",
"iconPath": "image/wechat.png",
"edIconPath": "image/wechatHL.png",
"text": "組件"
}, {
"pagePath": "page/API/index/index",
"iconPath": "image/wechat.png",
"edIconPath": "image/wechatHL.png",
"text": "接口"
}]
},
"networkTimeout": {
"request": 10000,
"connectSocket": 10000,
"uploadFile": 10000,
"downloadFile": 10000
},
"debug": true
}
2. 微信小程序的部署流程
微信小程序的整個(gè)開發(fā)與使用流程都在微信的體系中,所以安裝和使用應(yīng)該都很輕量。
微信采用云端編譯打包的方式,將編譯后的文件發(fā)送到微信上,接著,微信內(nèi)置的解析器會解析并渲染這個(gè)文件。
簡而言之,微信小程序的開發(fā)體驗(yàn)還算流暢,代碼可讀性也很高,也不需要做太多新的知識儲備,但是有硬傷,后文會分析。