現學現賣微信小程序開發(一)
現學現賣微信小程序開發(三):引入Rx,爲小程序插上翅膀javascript
好的,那麼下一步咱們就先照貓畫虎,新建一個todos文件夾,而後一套四樣同名文件準備齊全css
先在app.json中報個到,在pages中加入 "pages/todos/todos"
。接下來把首頁 index.js
中的導航改成 ../todos/todos
html
//事件處理函數
bindViewTap: function() {
wx.navigateTo({
url: '../todos/todos'
})
},複製代碼
而後呢,咱們簡單的先寫一個界面,其實什麼都沒有,就是一個view。把 todos.wxml
改爲下面的模樣:java
<!--todos.wxml-->
<view class="container todo-list">
</view>複製代碼
而後把導航欄標題設置一下,叫 Awesome Todos
吧,把 todos.json
改爲下面的樣子:web
{
"navigationBarTitleText": "Awesome Todos"
}複製代碼
樣式呢,也很是簡單粗暴的來一個吧:npm
.todo-list {
display: block;
padding: 40rpx;
width: 100vw;
margin: 0 auto;
}複製代碼
好的,下面咱們要寫關鍵的 todos.js
了。在寫以前,咱們須要一個服務器提供數據,這裏介紹一個能夠很是快速便捷的搭建一個仿真Web API的利器:json-server。 使用 npm i -g json-server
安裝,而後隨便挑一個目錄建一個todos-data.json 文件:json
{
"todos": [
{
"id": 1,
"desc": "have breakfast",
"completed": false
},
{
"id": 2,
"desc": "have lunch",
"completed": false
},
{
"id": 3,
"desc": "take a break",
"completed": false
},
{
"id": 4,
"desc": "having fun",
"completed": false
},
{
"id": 5,
"desc": "新的服務器版本不錯",
"completed": true
}
]
}複製代碼
這個時候,你的Web API就差一步之遙了,如今在命令行窗口敲入 json-server ./todos-data.json
就大功告成了。小程序
你能夠打開瀏覽器輸入 http://localhost:3000/todos
看看是否返回的是咱們的數據。這個Web API是徹底RESTful的,也就是說微信小程序
http://localhost:3000/todos
http://localhost:3000/todos/id
,好比id是1,那麼訪問http://localhost:3000/todos/1
http://localhost:3000/todos/id
http://localhost:3000/todos/id
http://localhost:3000/todos
咱們一開始的 todos.js
是這個樣子的:api
const URL = 'http://localhost:3000/todos'
let pageParams = {
data: { todos: [], desc: '' }
}
pageParams.onLoad = function () {
const that = this
wx.request({
url: URL,
data: JSON.stringify({}),
header: { 'content-type': 'application/json' },
method: 'GET',
success: res => {
console.log(res.data)
that.setData({
todos: res.data
})
},
fail: () => console.error('something is wrong'),
complete: () => console.log('todos loaded')
})
}
Page(pageParams)複製代碼
這段代碼很是簡單,建立一個pageParams對象並給本地數據初始化。而後定義onLoad生命週期函數,利用 wx.request
建立一個 HTTP GET 請求取得返回的數據,而後用setData去更新本地數據。注意一點 const that = this
是一個經常使用的避免 this
的context出現切換時出現問題的小技巧。再有就是咱們沒法直接寫入data,只能使用setData方法來進行更新。
那麼咱們看看是否成功吧,點擊左側的調試,而後點首頁的頭像進入咱們的todo頁面,固然如今界面上啥也沒有,但Console中仍是有料滴。
既然API調通了,咱們就來讓結果顯示到頁面上吧,首先改造頁面以下。
<!--todos.wxml-->
<view class="container todo-list">
<block wx:for="{{todos}}" wx:for-item="todo" wx:key="todo.id">
<view class="todo-item">
<text class="desc">{{todo.desc}}</text>
</view>
</block>
</view>複製代碼
這段代碼中,view
是個視圖容器,感受能夠把它想象成HTML中的div。微信小程序中除了 view
以外,目前還提供了 scroll-view
和 swiper
兩種容器,顧名思義 scroll-view
是用於可滾動的場景,而 swiper
是用於能夠手指滑動切換內容的場景。
在組件上使用 wx:for
綁定一個數組,便可使用數組中各項的數據重複渲染該組件。wx:for-item
意思是設定數組當前元素的變量名。wx:key
設置列表中項目的惟一的標識符。注意提供wx:key
能夠提高從新渲染時的性能,因此儘可能提供。
block
是一個挺怪的設計,它不是一個可視化的元素,感受純粹爲提供數據綁定而準備,在數據綁定時,以 block
來組織比較複雜的組件組合。因此block
這一段的意思就是對於數組todos中的每個todo,重複渲染下面這段
<view class="todo-item">
<text class="desc">{{todo.desc}}</text>
</view>複製代碼
固然咱們也須要拓展一下css,哦,不對,是wxss。
.todo-list {
display: block;
padding: 40rpx;
width: 100vw;
margin: 0 auto;
}
.todo-item {
display: flex;
flex-direction: row;
flex-basis: 1;
justify-content: space-around;
align-items: stretch;
width: 80 vw;
padding: 20rpx;
border-bottom: 1rpx solid #ededed;
}
.desc {
vertical-align: middle;
flex-grow: 1;
}複製代碼
如今看一下效果,列表成功顯示了。
如今咱們給Todos添加兩個功能吧:Toggle(切換完成狀態)和Remove(刪除該事項)。這樣的話,須要給todo的描述以前加一個完成狀態的複選框以及一個在todo的描述以後的刪除按鈕。咱們沒有使用微信提供的 checkbox
,而是用 icon
組件和 wx:if
來作處理,目的也是多展現一些特性。
<!--todos.wxml-->
<view class="container todo-list">
<block wx:for="{{todos}}" wx:for-item="todo" wx:key="todo.id">
<view class="todo-item">
<icon bindtap="toggleTodo" data-todo="{{todo}}" class="icon" type="success" wx:if="{{todo.completed}}"></icon>
<icon bindtap="toggleTodo" data-todo="{{todo}}" class="icon" type="success_circle" wx:if="{{!todo.completed}}"></icon>
<text bindtap="toggleTodo" data-todo="{{todo}}" class="desc">{{todo.desc}}</text>
<icon bindtap="removeTodo" data-todo="{{todo}}" class="remove" type="clear"></icon>
</view>
</block>
</view>複製代碼
上面的模版中,咱們看到多了一些新面孔:
wx:if
:這個比較好理解,就是條件渲染,在todo已完成的狀態下顯示一個icon,未完成狀態下顯示另外一個icon。bindtap
:這個是什麼呢?它是微信小程序提供的綁定事件的機制,其綁定表達式爲:bind+事件="事件處理函數"。咱們上面的例子中的 bindtap="toggleTodo"
就是對於tap(觸碰後立刻離開)事件處理是一個在Page中定義的叫 toggleTodo
的函數。data-todo
:不少時候咱們須要在事件傳遞時攜帶一些數據過去,好比Toggle這個功能,咱們須要在事件處理函數中知道是哪一個todo要切換完成狀態。data-todo
就是定義要傳輸的數據用的,data代表是要在 事件中傳輸的數據,然後面的todo代表這個數據在dataset中的key,經過這個key咱們能夠在Page中使用 event.target.dataset.todo
獲得這個數據。這也意味着咱們能夠經過多個key傳遞多個數據。值的注意的一點是除了 bindXXX
這種綁定事件的形式外,還有一種形式是 catchXXX
,它們的區別是 bind
事件綁定不會阻止冒泡事件向上冒泡,catch
事件綁定能夠阻止冒泡事件向上冒泡。什麼是冒泡呢?事件會繼續向上(父組件或父節點)傳遞就是冒泡,反之就是非冒泡。
在微信小程序中,冒泡的事件以下表列出的,其餘如沒有特殊的聲明都是非冒泡事件
事件 | 觸發條件 |
---|---|
touchstart | 手指觸摸動做開始 |
touchmove | 手指觸摸後移動 |
touchcancel | 手指觸摸動做被打斷,如來電提醒,彈窗 |
touchend | 手指觸摸動做結束 |
tap | 手指觸摸後立刻離開 |
longtap | 手指觸摸後,超過350ms再離開 |
對於這些冒泡事件來講,若是咱們要阻止其冒泡的行爲,可使用 catchXXX
來綁定事件。
const URL = 'http://localhost:3000/todos'
let pageParams = {
data: { todos: [], desc: '' }
}
pageParams.onLoad = function () {
const that = this
wx.request({
url: URL,
data: JSON.stringify({}),
header: { 'content-type': 'application/json' },
method: 'GET',
success: res => {
console.log(res.data)
that.setData({
todos: res.data
})
},
fail: () => console.error('something is wrong'),
complete: () => console.log('get req completed')
})
}
pageParams.toggleTodo = function (event) {
const that = this
const selectedTodo = event.target.dataset.todo
const url = `${URL}/${selectedTodo.id}`
const updatedTodo = Object.assign({}, selectedTodo, {completed: !selectedTodo.completed})
wx.request({
url: url,
data: JSON.stringify(updatedTodo),
header: { 'content-type': 'application/json' },
method: 'PUT',
success: res => {
console.log(res.data)
that.setData({
todos: that.data.todos.map(todo => {
if(todo.id === updatedTodo.id){
return updatedTodo
}
return todo
})
})
},
fail: () => console.error('something is wrong'),
complete: () => console.log('toggle req completed')
})
}
pageParams.removeTodo = function (event) {
const that = this
const selectedTodo = event.target.dataset.todo
const url = `${URL}/${selectedTodo.id}`;
wx.request({
url: url,
data: JSON.stringify(selectedTodo),
header: { 'content-type': 'application/json' },
method: 'DELETE',
success: res => {
console.log(res.data)
that.setData({
todos: that.data.todos.filter(todo => todo.id !== selectedTodo.id)
})
},
fail: () => console.error('something is wrong'),
complete: () => console.log('delete req completed')
})
}
Page(pageParams)複製代碼
接下來的事情就變的很簡單,咱們在 todos.js
中增長兩個處理函數用於處理toggle和remove,事件處理函數有一個參數就是event。處理邏輯仍是先提交HTTP請求處理服務器端數據,處理成功後再處理本地內存數據。
固然 wxss
再更新一下:
.todo-list {
display: block;
padding: 40rpx;
width: 100vw;
margin: 0 auto;
}
.todo-item {
display: flex;
flex-direction: row;
flex-basis: 1;
justify-content: space-around;
align-items: stretch;
width: 80 vw;
padding: 20rpx;
border-bottom: 1rpx solid #ededed;
}
.icon {
vertical-align: middle;
}
.remove {
float: right;
align-self: flex-end;
}
.desc {
vertical-align: middle;
flex-grow: 1;
}複製代碼
如今的效果是這樣滴
新增Todo、過濾器、優化代碼結構、引入Rx等話題咱們後面繼續,此次就先到這裏。