完成练习的小程序
看了公文介绍,想找一个简单的例子来验证一下实现。TodoList MVC非常好,简单易行。
以前,JQ、基干和vue只是简单使用,它们的功能如下:
添加todo并将其存储在应用程序缓存列表中。显示差异化状态显示:全部、未完成、已完成。更改待办事项状态并删除待办事项。根据以上功能,小程序完成如下:
GitHub:github.com/CH563/TodoL…
下面记录一下我的完成过程:
下载小程序开发工具:开发者工具下载
安装完成后,用微信扫描登录,选择一个文件夹并创建。开发工具将自动生成以下目录:
页数/
app.js
app.json
app.wxss
文档结构和具体配置。查看官方文件:mp.weixin.qq.com/debug/wxado…
基本配置
因为平时的开发习惯是Less,如果小程序直接用wxss编写,会恢复原生的编写方法,非常不方便,所以直接用name实时编译Less,把文件名修改为wxss。小程序开发工具不支持Less,所以直接用vscode开发。小程序开发工具只能实时预览和调试。vscode还有丰富的小程序语法提示插件。
//gulf file . jsvar大口=require('大口')var less=require('大口-less ')var plunger=require('大口-plunger ')var rename=require('大口-rename ')大口. task('less ',Function(){ return glaugh . src('。/app.less ')。管道(plummer())//错误处理。管道(less()) //编译less.pipe(重命名((路径)=path.extname=')。wxss’)/。});大口。看着。/app.less ',[' less ']);//实时监控app.less文件变化,运行任务UI组件也直接引用applet支持的weui-wxss。
@import。/weui . wxss ';在app.json中定义小程序页面路由和颜色匹配:
{ ' pages ' :[' pages/index/index '],' window ' : { ' backgroundTextStyle ' : ' light ',' navigationBarBackgroundColor ' : ' # ca 2100 ','导航栏标题文本' : ' TodoList ','导航栏文本样式' :' white'}
页面开发
页文件存储在pages/目录中,将为每个功能页创建一个文件夹现在todolist只需要一页就可以完成。
数据绑定使用小胡子语法(双括号)包装变量。
text class=' userinfo-昵称' {userInfo .昵称}}/text!-三元运算-文本类=' {{{ status===' 1 '?'active ' : ' ' } } ' data-status=' 1 ' bind tap=' show status ' all/text
添加todo
只需使用字段addShow判断输入图层是显示还是隐藏。
这里输入输出框不是双向绑定,所以添加一个事件bindinput='setI '
nput"来赋值实时变化<view class="addForm {{addShow?'':'hide'}}"> <view class="addForm-div"> <input class="weui-input" placeholder="请输入todo" value="{{addText}}" bindinput="setInput" focus="{{focus}}" /> <view class="addForm-btn"> <button class="weui-btn mini-btn" type="warn" bindtap="addTodo" size="mini">确定添加</button> <button class="weui-btn mini-btn" type="default" bindtap="addTodoHide" size="mini">取消</button> </view> </view> </view>
实时赋值事件处理
setInput: function (e) { this.setData({ addText: e.detail.value })}
取消时,需要清空input的值,input里需要绑定value="{{addText}}"
Page({ data:{ //... }, //... addTodoHide: function () { this.setData({ addShow: false, // 控制添加输入面板隐藏 focus: false, // 失去焦点 addText: '' // 清空值 }) } //...})
添加todo
Page({ data:{ //... }, //... addTodo: function () { // 检查有没有输入 if (!this.data.addText.trim()) { return } var temp = this.data.lists // 取出lists var addT = { id: new Date().getTime(), // 取当前时间 title: this.data.addText, status: '0' } temp.push(addT) // 添加新的todo this.showCur(temp) // 处理当前状态的方法 this.addTodoHide() // 添加成功后,隐藏添加面板方法 wx.setStorage({ // 小程序异步缓存 key:"lists", data: temp }) wx.showToast({ // weui toast组件 title: '添加成功!', icon: 'success', duration: 1000 }); } //...})
列表部分
scroll-view内滚动
列表渲染,事件触发,利用data传参,bind绑定事件
<scroll-view class="lists" scroll-y> <!-- 判断列表是否为空 --> <block wx:if="{{curLists.length < 1}}"> <view class="nodata">暂无数据</view> </block> <!-- 列表渲染 --> <view class="item" wx:for="{{curLists}}" wx:key="index"> <!-- 内容view,绑定touch三个件事,来实现滑动册除 --> <view class="content" style="{{item.txtStyle}}" data-index="{{index}}" bindtouchstart="touchS" bindtouchmove="touchM" bindtouchend="touchE"> <!-- checkbox图标,changeTodo事件来控制状态切换 --> <icon class="icon-small" type="{{item.status === '0'?'circle':'success'}}" size="23" data-item="{{item.id}}" bindtap="changeTodo"></icon> <text class="title {{item.status === '1'?'over':''}}">{{item.title}}</text> <!-- api.formatTime是使用了wxs模块化编写的模块 --> <text class="time">{{api.formatTime(item.id)}}</text> </view> <!-- 删除按钮,绑定删除事件 --> <view class="del" data-item="{{item.id}}" bindtap="delTodo"><text>删除</text></view> </view> </scroll-view>
滑动删除
效果:当向左滑动时,content跟随手指像左移动,同时右侧出现del按钮;当滑动距离大于按钮宽度一半松开手指时自动滑动到左侧显示出按钮,小于一半时自动回到原来的位置,隐藏按钮。
实现思路:content和del按钮分别是绝对定位,利用z-index层来控制让content来盖住del,当content向左滑动时,del按钮就会露出来。
微信小程序api提供的touch对象和3个有关手指触摸的函数(touchstart,touchmove,touchend)来实现content随手指移动
详细api说明,请查看:mp.weixin.qq.com/debug/wxado…
列表的content已绑定这个三个事件:bindtouchstart="touchS" bindtouchmove="touchM" bindtouchend="touchE"
实现方法:
注意txtStyle,在content在绑定这个属性的,实现跟随手指移动的style="{{item.txtStyle}}"
delBtnWidth为了del按钮的宽度,这里以rpx为单位
Page({ data:{ //... }, //... touchS: function (e) { // console.log('开始:' + JSON.stringify(e)) // 是否只有一个触摸点 if(e.touches.length === 1){ this.setData({ // 触摸起始的X坐标 startX: e.touches[0].clientX }) } }, touchM: function (e) { // console.log('移动:' + JSON.stringify(e)) var _this = this if(e.touches.length === 1){ // 触摸点的X坐标 var moveX = e.touches[0].clientX // 计算手指起始点的X坐标与当前触摸点的X坐标的差值 var disX = _this.data.startX - moveX // delBtnWidth 为右侧按钮区域的宽度 var delBtnWidth = _this.data.delBtnWidth var txtStyle = '' if (disX == 0 || disX < 0){ // 如果移动距离小于等于0,文本层位置不变 txtStyle = 'left:0' } else if (disX > 0 ){ // 移动距离大于0,文本层left值等于手指移动距离 txtStyle = 'left:-' + disX + 'rpx' if(disX >= delBtnWidth){ // 控制手指移动距离最大值为删除按钮的宽度 txtStyle = 'left:-' + delBtnWidth + 'rpx' } } // 获取手指触摸的是哪一个item var index = e.currentTarget.dataset.index; var list = _this.data.curLists // 将拼接好的样式设置到当前item中 list[index].txtStyle = txtStyle // 更新列表的状态 this.setData({ curLists: list }); } }, touchE: function (e) { // console.log('停止:' + JSON.stringify(e)) var _this = this if(e.changedTouches.length === 1){ // 手指移动结束后触摸点位置的X坐标 var endX = e.changedTouches[0].clientX // 触摸开始与结束,手指移动的距离 var disX = _this.data.startX - endX var delBtnWidth = _this.data.delBtnWidth // 如果距离小于删除按钮的1/2,不显示删除按钮 var txtStyle = disX > delBtnWidth/2 ? 'left:-' + delBtnWidth + 'rpx' : 'left:0' // 获取手指触摸的是哪一项 var index = e.currentTarget.dataset.index var list = _this.data.curLists list[index].txtStyle = txtStyle // 更新列表的状态 _this.setData({ curLists: list }); } } //...})
WXS实现时间格式
实现在效果如下:
这里我使用小程序的WXS
WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。了解详细
新建一个api.wxs文件,然后在index.wxml引用,定义模块名即可引用:
<!-- index.wxml --><wxs src="./api.wxs" module="api" />...<text class="time">{{api.formatTime(item.id)}}</text>
每个 wxs 模块均有一个内置的 module 对象
api.wxs文件和时间格式实现方法:
var formatTime = function(time){ // 获取当前时间 var getUnix = function () { var date = getDate() return date.getTime() } // 获取今天零点时间 var getTodayUnix = function () { var date = getDate() date.setHours(0) date.setMinutes(0) date.setSeconds(0) date.setMilliseconds(0) return date.getTime() } // 获取今年的1月1日零点时间 var getYearUnix = function () { var date = getDate() date.setMonth(0) date.setDate(1) date.setHours(0) date.setMinutes(0) date.setSeconds(0) date.setMilliseconds(0) return date.getTime() } // 获取标准时间 var getLastDate = function (time) { var date = getDate(time) var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 var day = date.getDay() < 10 ? '0' + (date.getDay()) : date.getDay() return date.getFullYear() + '-' + month + '-' + day } // 转换时间 var getFormatTime = function (timestamp) { var now = getUnix() var today = getTodayUnix() var year = getYearUnix() var timer = (now - timestamp) / 1000 var tip = '' if (timer <= 0) { tip = '刚刚' } else if (Math.floor(timer / 60) <= 0) { tip = '刚刚' } else if (timer < 3600) { tip = Math.floor(timer / 60) + '分钟前' } else if (timer >= 3600 && (timestamp - today >= 0)) { tip = Math.floor(timer / 3600) + '小时前' } else if (timer / 86400 <= 31) { tip = Math.ceil(timer / 86400) + '天前' } else { tip = getLastDate(timestamp) } return tip } return getFormatTime(+time)}// es6方法一样,导出formatTime方法module.exports.formatTime = formatTime;
这里需要注意的是获取当前时间,WXS是不支持new Date(),它有自己本身的方法getDate()。使用方法跟new Date()一样。
至此已完成,TodoList实践例子,功能简单,入门好例子。
希望对大家有帮助,不足的地方请大家指点,刚啃完官方文档撸的例子。