看完官方的文檔介紹后,就想找個簡單的例子來驗證實現(xiàn)一下,TodoList MVC就很好了,簡單容易。 之前都用JQ、Backbone、vue簡單擼過,大概功能如下:
根據(jù)以上功能,小程序完成如下: GitHub: github.com/CH563/TodoL…
下面記錄一下我的完成過程:下載小程序開發(fā)工具:開發(fā)者工具下載 安裝完成后,使用微信掃一掃登錄,選好文件夾后創(chuàng)建即可,開發(fā)工具會自動生成以下目錄: pages/ app.js app.json app.wxss 文錄紹構(gòu)和具體配置查看官方文檔: mp.weixin.qq.com/debug/wxado… 基本配置由于平時開發(fā)習慣用Less,如果在直接使用小程序的wxss來編寫的話,就恢復(fù)原生編寫方式,大大的不便,所以直接使用了gulp來實時編譯Less,和修改文件名為wxss。小程序開發(fā)工具是不支持Less,直接用vscode來開發(fā),小程序開發(fā)工具是用實時預(yù)覽和調(diào)試即可,vscode也有豐富的插件支待小程序語法提示。 // gulpfile.js var gulp = require('gulp') var less = require('gulp-less') var plumber = require('gulp-plumber') var rename = require('gulp-rename') gulp.task('less', function () { return gulp.src('./app.less') .pipe(plumber()) // 錯誤處理 .pipe(less()) // 編譯less .pipe(rename((path) => path.extname = '.wxss')) // 編譯后生成文件修改后綴為.wxss .pipe(gulp.dest('./')); }); gulp.watch('./app.less', ['less']); // 實時監(jiān)控app.less文件變化,運行任務(wù) UI組件也直接引用了小程序支持的 weui-wxss @import "./weui.wxss"; 在app.json定義好小程序頁面路由和配色: { "pages":[ "pages/index/index" ], "window":{ "backgroundTextStyle":"light", "navigationBarBackgroundColor": "#ca2100", "navigationBarTitleText": "TodoList", "navigationBarTextStyle":"white" } } 頁面開發(fā)頁面文件都存放在pages/目錄下,每個功能頁面都會創(chuàng)建一個文件夾,TodoList現(xiàn)只需一個頁面完成即可 數(shù)據(jù)綁定使用 Mustache 語法(雙大括號)將變量包起來 <text class="userinfo-nickname">{{userInfo.nickName}}</text> <!-- 三元運算 --> <text class="{{status === '1'?'active':''}}" data-status="1" bindtap="showStatus">全部</text> 添加todo使用字段 addShow 來判斷添加輸入層顯示隱藏即可 input輸出框這里不是雙向綁定,所以這里添加一個事件 bindinput="setInput" 來賦值實時變化 <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) // 處理當前狀態(tài)的方法 this.addTodoHide() // 添加成功后,隱藏添加面板方法 wx.setStorage({ // 小程序異步緩存 key:"lists", data: temp }) wx.showToast({ // weui toast組件 title: '添加成功!', icon: 'success', duration: 1000 }); } //... }) 列表部分scroll-view內(nèi)滾動 列表渲染,事件觸發(fā),利用data傳參,bind綁定事件 <scroll-view class="lists" scroll-y> <!-- 判斷列表是否為空 --> <block wx:if="{{curLists.length < 1}}"> <view class="nodata">暫無數(shù)據(jù)</view> </block> <!-- 列表渲染 --> <view class="item" wx:for="{{curLists}}" wx:key="index"> <!-- 內(nèi)容view,綁定touch三個件事,來實現(xiàn)滑動冊除 --> <view class="content" style="{{item.txtStyle}}" data-index="{{index}}" bindtouchstart="touchS" bindtouchmove="touchM" bindtouchend="touchE"> <!-- checkbox圖標,changeTodo事件來控制狀態(tài)切換 --> <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跟隨手指像左移動,同時右側(cè)出現(xiàn)del按鈕;當滑動距離大于按鈕寬度一半松開手指時自動滑動到左側(cè)顯示出按鈕,小于一半時自動回到原來的位置,隱藏按鈕。 實現(xiàn)思路:content和del按鈕分別是絕對定位,利用z-index層來控制讓content來蓋住del,當content向左滑動時,del按鈕就會露出來。 微信小程序api提供的touch對象和3個有關(guān)手指觸摸的函數(shù)(touchstart,touchmove,touchend)來實現(xiàn)content隨手指移動
詳細api說明,請查看: mp.weixin.qq.com/debug/wxado… 列表的content已綁定這個三個事件: bindtouchstart="touchS" bindtouchmove="touchM" bindtouchend="touchE" 實現(xiàn)方法: 注意 txtStyle ,在content在綁定這個屬性的,實現(xiàn)跟隨手指移動的 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 為右側(cè)按鈕區(qū)域的寬度 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 // 將拼接好的樣式設(shè)置到當前item中 list[index].txtStyle = txtStyle // 更新列表的狀態(tài) this.setData({ curLists: list }); } }, touchE: function (e) { // console.log('停止:' + JSON.stringify(e)) var _this = this if(e.changedTouches.length === 1){ // 手指移動結(jié)束后觸摸點位置的X坐標 var endX = e.changedTouches[0].clientX // 觸摸開始與結(jié)束,手指移動的距離 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 // 更新列表的狀態(tài) _this.setData({ curLists: list }); } } //... }) WXS實現(xiàn)時間格式實現(xiàn)在效果如下:
這里我使用小程序的WXS WXS(WeiXin Script)是小程序的一套腳本語言,結(jié)合 WXML,可以構(gòu)建出頁面的結(jié)構(gòu)。了解詳細 新建一個api.wxs文件,然后在index.wxml引用,定義模塊名即可引用: <!-- index.wxml --> <wxs src="./api.wxs" module="api" /> ... <text class="time">{{api.formatTime(item.id)}}</text> 每個 wxs 模塊均有一個內(nèi)置的 module 對象 api.wxs文件和時間格式實現(xiàn)方法: 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 } // 轉(zhuǎn)換時間 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方法一樣,導(dǎo)出formatTime方法 module.exports.formatTime = formatTime; 這里需要注意的是獲取當前時間,WXS是不支持 new Date() ,它有自己本身的方法 getDate() 。使用方法跟 new Date() 一樣。 至此已完成,TodoList實踐例子,功能簡單,入門好例子。 希望對大家有幫助,不足的地方請大家指點,剛啃完官方文檔擼的例子。 |