作者:Eraser's,來自授權(quán)地址最近,由于工作需要開始了解微信小程序,雖然小程序已經(jīng)出了很久了,剛出的那段時間很火,看到很多關(guān)于小程序的技術(shù)文章,不過現(xiàn)在似乎沒那么火了,anyway,我們還是可以學(xué)習(xí)下的。一、 ...
最近,由于工作需要開始了解微信小程序,雖然小程序已經(jīng)出了很久了,剛出的那段時間很火,看到很多關(guān)于小程序的技術(shù)文章,不過現(xiàn)在似乎沒那么火了,anyway,我們還是可以學(xué)習(xí)下的。
最近,由于工作需要開始了解微信小程序,雖然小程序已經(jīng)出了很久了,剛出的那段時間很火,看到很多關(guān)于小程序的技術(shù)文章,不過現(xiàn)在似乎沒那么火了,anyway,我們還是可以學(xué)習(xí)下的。
1.理念:小程序開發(fā)框架的目標(biāo)是通過盡可能簡單、高效的方式讓開發(fā)者可以在微信中開發(fā)具有原生 APP 體驗的服務(wù)。
2.框架:框架的核心是一個響應(yīng)的數(shù)據(jù)綁定系統(tǒng)。整個系統(tǒng)分為兩塊視圖層(View)和邏輯層(App Service),框架可以讓數(shù)據(jù)與視圖非常簡單地保持同步。當(dāng)做數(shù)據(jù)修改的時候,只需要在邏輯層修改數(shù)據(jù),視圖層就會做相應(yīng)的更新。
3.相關(guān)資料:調(diào)試工具下載,簡易教程
初步了解這些基本信息后,我們先來看下TODOS這個應(yīng)用做出來的最終效果
功能演示:

目錄結(jié)構(gòu):

主要功能模塊為:
下面我們詳細(xì)介紹下
{
"pages":[
"pages/index/index", // 設(shè)置頁面路徑,項目打開后找到這個路徑下的文件
"pages/logs/logs"
],
"window":{ // 設(shè)置默認(rèn)頁面的窗口表現(xiàn)
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "TODOS",
"navigationBarTextStyle":"black"
},
"tabBar": { // 設(shè)置底部tab的表現(xiàn)
"borderStyle": "white",
"backgroundColor": "#f5f5f5",
"selectedColor": "#222",
"list": [ // 對應(yīng)底部下面兩個菜單項;TODOS和LOGS
{
"pagePath": "pages/index/index",
"text": "TODOS",
"iconPath": "images/home.png",
"selectedIconPath": "images/home-actived.png"
},
{
"pagePath": "pages/logs/logs",
"text": "LOGS",
"iconPath": "images/note.png",
"selectedIconPath": "images/note-actived.png"
}
]
}
}
App() 函數(shù)用來注冊一個小程序。接受一個 object 參數(shù),其指定小程序的生命周期函數(shù)等。App() 必須在 app.js 中注冊,且不能注冊多個。
示例代碼
App({
onLaunch: function() {
// Do something initial when launch.
},
onShow: function() {
// Do something when show.
},
onHide: function() {
// Do something when hide.
},
onError: function(msg) {
console.log(msg)
},
globalData: 'I am global data'
})
在這個項目中不需要加什么代碼在App({})中,所以文件中只有一個App({})
app.wxss文件主要可以設(shè)置一些全局樣式
page {
height: 100%;
font-family: "Helvetica Neue", Helvetica, Arial;
}
Page() 函數(shù)用來注冊一個頁面。接受一個 object 參數(shù),其指定頁面的初始數(shù)據(jù)、生命周期函數(shù)、事件處理函數(shù)等。
// ===== 頁面數(shù)據(jù)對象 =====
data: {
input: '',
todos: [],
leftCount: 0,
allCompleted: false,
logs: [],
addOneLoading: false,
loadingHidden: true,
loadingText: '',
toastHidden: true,
toastText: '',
clearAllLoading: false
},
初始化數(shù)據(jù)作為頁面的第一次渲染。data將會以JSON的形式由邏輯層傳至渲染層,其數(shù)據(jù)可以是:字符串,數(shù)字,布爾值,對象,數(shù)組。
渲染層可以通過WXML對數(shù)據(jù)進行綁定。
<input class="new-todo" value="{{ input }}" placeholder="Anything here..." auto-focus bindinput="inputChangeHandle" bindchange="addTodoHandle"/>
如上述代碼中的input.
// ===== 頁面生命周期方法 =====
onLoad: function () {
// 從緩存獲取任務(wù)列表數(shù)據(jù),并用setData設(shè)置
var todos = wx.getStorageSync('todo_list') // 調(diào)用 WX API 從本地緩存中獲取數(shù)據(jù)
if (todos) {
var leftCount = todos.filter(function (item) {
return !item.completed
}).length
this.setData({ todos: todos, leftCount: leftCount })
}
// 設(shè)置logs數(shù)據(jù)
var logs = wx.getStorageSync('todo_logs')
if (logs) {
this.setData({ logs: logs })
}
},
addTodoHandle: function (e) {
if (!this.data.input || !this.data.input.trim()) return
this.setData( {
addOneLoading: true
});
//open loading
this.setData( {
loadingHidden: false,
loadingText: 'Waiting...'
});
var todos = this.data.todos
todos.push({ name: this.data.input, completed: false })
var logs = this.data.logs
logs.push({ timestamp: new Date().toLocaleString(), action: '新增', name: this.data.input })
this.setData({
input: '',
todos: todos,
leftCount: this.data.leftCount + 1,
logs: logs
})
this.save()
},
save: function () {
wx.setStorageSync('todo_list', this.data.todos)
wx.setStorageSync('todo_logs', this.data.logs)
//close loading and toggle button loading status
var self = this;
setTimeout( function() {
self.setData( {
loadingHidden: true,
addOneLoading: false,
loadingText: ''
});
}, 100);
},
主要把時間new Date().toLocaleString(), action:'新增',事件名 name: this.data.input這三個字段push到todos這個data數(shù)據(jù)中;然后在save()中通過wx.setStorageSync('todo_list', this.data.todos)設(shè)置緩存。
toggleTodoHandle: function (e) {
var index = e.currentTarget.dataset.index
var todos = this.data.todos
todos[index].completed = !todos[index].completed
var logs = this.data.logs
logs.push({
timestamp: new Date().toLocaleString(),
action: todos[index].completed ? '標(biāo)記完成' : '標(biāo)記未完成',
name: todos[index].name
})
this.setData({
todos: todos,
leftCount: this.data.leftCount + (todos[index].completed ? -1 : 1),
logs: logs
})
this.save()
},
var index = e.currentTarget.dataset.index 獲取當(dāng)前索引,對應(yīng)的wxml代碼為:
<view class="item{{ item.completed ? ' completed' : '' }}" wx:for="{{ todos }}" wx:key="{{ index }}" bindtap="toggleTodoHandle" data-index="{{ index }}">
<!-- completed: success, todo: circle -->
<icon class="checkbox" type="{{ item.completed ? 'success' : 'circle' }}"/>
<text class="name">{{ item.name }}</text>
<icon class="remove" type="clear" size="16" catchtap="removeTodoHandle" data-index="{{ index }}"/>
</view>
bindtap: 當(dāng)用戶點擊該組件的時候會在該頁面對應(yīng)的Page中找到相應(yīng)的事件處理函數(shù)
最后考慮到了loading的效果,要利用button組件的loading屬性來實現(xiàn)。但是loading僅僅是一個樣式的控制,它不會控制這個按鈕是否能重復(fù)點擊。所以還要利用button的disabled屬性,防止重復(fù)點擊。
<button type="primary" size="mini" bindtap="addTodoHandle" loading="{{addOneLoading}}" disabled="{{addOneLoading}}">
+ Add
</button>
js:
loadingChange: function() {
this.setData({
loadingHidden: true,
loadingText: ''
});
},
toastChange: function() {
this.setData( {
toastHidden: true,
toastText: ''
});
}
LOGS頁面比較簡單,主要通過var logs = wx.getStorageSync('todo_logs')
獲取logs列表,然后在頁面渲染,這里就不貼代碼了。
至此,基本了解了TODOS應(yīng)用的構(gòu)建過程,通過代碼詳解、參考微信小程序官方文檔了解了微信自家開發(fā)的視圖層描述語言WXML和WXSS,以及基于 JavaScript 的邏輯層框架;與HTML頁面結(jié)構(gòu)相似,對應(yīng)HTML,CSS,JAVASCRIPT; 所以學(xué)習(xí)起來比較容易。不過僅僅通過這個TODOS應(yīng)用,還只是了解小程序這個平臺的一些基本用法。復(fù)雜一點,頁面跳轉(zhuǎn),網(wǎng)絡(luò)請求等都需要我們?nèi)嵺`,才能對小程序了解得更多。
完整代碼:
源代碼
參考資料:
1.https://github.com/zce/weapp-todos
2.http://www.cnblogs.com/lyzg/p/5906496.html