现学现卖微信小程序开发(一)
现学现卖微信小程序开发(三):引入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等话题咱们后面继续,此次就先到这里。