博客班級 | https://edu.cnblogs.com/campus/zjcsxy/SE2020 |
作業要求 | https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11334 |
作業目標 |
|
作業源代碼 | https://github.com/aiai0603/software-engineering-demo-1.git |
學號/姓名 | 31801150/張帥 |
院系 | 浙大城市學院計算機系 |
前言:軟件工程課程的第一次作業,單獨完成一個簡單的微信小程序(不含后台),本文主要講解如何從0基礎入門來編寫,含源代碼和注解。本人純小白,大佬勿噴,有錯誤請批評指正。
最終作品地址:https://github.com/aiai0603/software-engineering-demo-1.git(僅供參考)
開發工具:微信開發者工具
效果演示
(預覽版)
全局配置
app.json:
pages:配置微信的小程序的所有頁面。第一項"pages/index/index"為默認顯示的界面,本程序包含9個界面。
1 "pages/index/index", //個人信息首頁 2 "pages/logs/logs", //獎券列表展示頁 3 "pages/main/main", //主頁 4 "pages/rule/rule", //積分規則 5 "pages/policy/policy", //隱私政策 6 "pages/score/score", //積分頁面 7 "pages/set/set", //個人設置 8 "pages/show/show", //領券頁面 9 "pages/shop/shop" //積分商店
windows:全局配置頁面效果,具體請參看官方文檔:https://developers.weixin.qq.com/miniprogram/dev/framework/config.html
1 "window":{ 2 "backgroundTextStyle":"dark", 3 "navigationBarBackgroundColor": "#f21515", 4 "navigationBarTitleText": "Happy everyday", 5 "navigationBarTextStyle":"black", 6 "enablePullDownRefresh": true 7 },
tabbar:下方導航條配置,設置導航條的文字和圖標
1 "tabBar": { 2 "selectedColor": "#f21515", //選中時文字顏色 3 "list": [{ 4 "pagePath": "pages/main/main", //跳轉的頁面 5 "text": "首頁", //文字 6 "iconPath":"pages/1.jpg" , //未選中時顯示的圖表 7 "selectedIconPath": "pages/1-1.jpg" //選中時的圖標 8 },{ 9 "pagePath": "pages/logs/logs", 10 "text": "優惠券", 11 "iconPath":"pages/3.jpg" , 12 "selectedIconPath": "pages/3-3.jpg" 13 },{ 14 "pagePath": "pages/index/index", 15 "text": "我的", 16 "iconPath":"pages/2.jpg" , 17 "selectedIconPath": "pages/2-2.jpg" 18 }] 19 }
app.js:
globalData:全局變量,用於存儲數據,模擬變化。
1 globalData: { 2 userInfo: null, //個人信息 3 disabled:false, //控制按鈕是否可用 4 color:"red", //控制按鈕顏色 5 pricenum:3, //控制持有券數 6 price:[ //持有券的列表 7 { 8 available:0, //是否可用 9 count:2, //折扣 10 money:3, //滿多少可用 11 name:"雪碧滿3減2券", //券名 12 day:"2020.1.1-2021.1.1可用" //說明 13 }........(此處省略) 14 ], 15 score:[{ //積分信息 16 day:"2020/10/11 12:00:31", //時間 17 title:"簽到獎勵", //說明 18 point:2 //獲得積分數 19 }........(此處省略)], 20 scorenum:506, //積分總數 21 sign:"簽到", //簽到按鈕文字 22 style:"qd" //簽到按鈕樣式名 23 }, 24
分頁代碼
在每一頁的json文件中,設置好每一頁的標題文字和顏色
1 { 2 "usingComponents": {}, //使用組建(本dome未使用) 3 "navigationBarTitleText": "我的", //標題文字 4 "navigationBarTextStyle":"white", //標題顏色 5 }


1 <view class="container"> 2 <view class="userinfo"> 3 <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo">授權登錄 </button> 4 <block wx:else> 5 <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image> 6 <text class="userinfo-nickname">{{userInfo.nickName}}</text> 7 </block> 8 </view>
index.js
1 onLoad: function () { 2 if (app.globalData.userInfo) { //如果全局變量中已經存在授權信息則賦值給當前頁面的變量 3 this.setData({ 4 userInfo: app.globalData.userInfo, 5 hasUserInfo: true 6 }) 7 } else if (this.data.canIUse){ 8 // 由於 getUserInfo 是網絡請求,可能會在 Page.onLoad 之后才返回 9 // 所以此處加入 callback 以防止這種情況 10 app.userInfoReadyCallback = res => { 11 this.setData({ 12 userInfo: res.userInfo, 13 hasUserInfo: true 14 }) 15 } 16 } else { 17 // 在沒有 open-type=getUserInfo 版本的兼容處理 18 wx.getUserInfo({ 19 success: res => { 20 app.globalData.userInfo = res.userInfo 21 this.setData({ 22 userInfo: res.userInfo, 23 hasUserInfo: true 24 }) 25 } 26 }) 27 } 28 }, 29 30 getUserInfo: function(e) { //獲得授權的者的微信名 31 console.log(e) 32 app.globalData.userInfo = e.detail.userInfo 33 this.setData({ 34 userInfo: e.detail.userInfo, 35 hasUserInfo: true 36 }) 37 }
下方為view標簽編寫的功能欄,使用navigator標簽實現跳轉到指定的頁面
PS:navigator標簽只能跳轉到非tabbar的頁面,跳轉到tabbar界面需要使用函數:
1 wx.switchTab({ //跳轉至tabbar頁面 2 url: '../logs/logs' 3 }) 4 5 <navigator url="../score/score"> //跳轉到非tabbar界面
pages/logs/logs(優惠券的展示頁面):
要調用全局變量,需要在js文件開頭寫上調用語句
1 var app=getApp();
將全局變量的值賦值給當前頁面的變量,即可在當前頁面使用
1 onShow: function () { 2 this.setData({ 3 price:app.globalData.price 4 })
頭部使用選項卡檢索“未使用”和“歷史記錄”的信息,綁定事件點擊切換
logs.wxml
1 <view id='tabs'> 2 <view class='tabs-box'> 3 <block wx:for="{{['未使用','歷史記錄']}}" wx:key="index"> 4 <view class="tabs-item {{currentTabIndex == index ? 'selected' : '' }}" bindtap='onTabsItemTap' data-index='{{index}}'> 5 {{item}} 6 </view> 7 </block> 8 </view> 9 <view class='ordert-detail'> 10 <view hidden='{{currentTabIndex != 0}}'>(省略) 11 </view> 12 <view hidden='{{currentTabIndex != 1}}'>(省略)
13 </view> 14 </view>
logs.js
1 onTabsItemTap:function(event){ 2 let index=event.currentTarget.dataset.index; 3 this.setData({ 4 currentTabIndex:index, 5 }) 6 }
使用wx:for將數據渲染到頁面中,使用availabel判斷為哪種優惠券,從而渲染到不同的選項下,並綁定不同的樣式
1 <view class="card" wx:for="{{price}}" wx:if="{{item.available!=0}}"> 2 <view class="left-2"> 3 <view class="left-title">¥{{item.count}}</view> 4 <view class="left-under">滿{{item.money}}元可用</view> 5 </view> 6 <view class="word"> 7 <view class="title"> 8 {{item.name}} 9 </view> 10 <view class="under"> 11 12 {{item.day}} 13 </view> 14 </view> 15 </view>
pages/policy/policy、pages/rule/rule、pages/set/set :(三張簡單的內容頁面,不過多贅述)
pages/main/main(主頁):
上方為與個人信息頁相同的授權判定,授權則顯示用戶信息,未授權則顯示登錄按鈕。簽到按鈕通過全局變量中的sign判斷是否曾簽到過,並在簽到后改變樣式
main.wxml
1 <view class="{{style}}" bindtap="sign" >{{sign}}</view>
main.js
1 var util = require('../../utils/util.js'); //導入官方自帶的js文件,內含時間處理函數 2 sign:function(){ 3 if( app.globalData.sign=="簽到") //判斷是否曾簽到 4 { 5 console.log("ok") 6 app.globalData.sign="已簽" 7 app.globalData.style="qd-1" //改變樣式 8 app.globalData.scorenum=app.globalData.scorenum+2 //改變總積分 9 var newpoint={ 10 day: util.formatTime(new Date()), 11 title:"簽到獎勵", 12 point:2 13 } 14 app.globalData.score.unshift(newpoint); //在積分信息數組中加入新的數據 15 this.setData({ //修改當前界面的數據,及時刷新 16 style:"qd-1", 17 sign:"已簽", 18 score:app.globalData.scorenum 19 }) 20 }else{ 21 } 22 },
下方使用swiper組件實現輪播
pages/show/show(領券頁面):
領券按鈕主要通過全局變量disabled判斷是否已經領過券,第一次領取則領取成功並彈窗
show.wxml
1 <button disabled="{{disabled}}" bindtap="get" style="width:200rpx;color:white;background-color:{{color}}" >領取</button>
show.js
get(){ wx.showToast({ //彈窗 title: '領取成功!', // 標題 icon: 'success', // 圖標類型,默認success duration: 1500 // 提示窗停留時間,默認1500ms }), app.globalData.color="grey", app.globalData.disabled=true, app.globalData.pricenum+=1, //修改了全局變量 console.log(app.globalData.disabled) this.setData({ color:"grey", disabled:true //在當前界面更新 }) var newprice={ available:0, count:2, money:4, name:"雪碧滿4減2券", day:"2020.1.1-2021.1.1可用" } app.globalData.price.push(newprice) //將新的優惠券信息插入全局數組中 },
pages/score/score(積分界面):
積分信息的渲染同優惠券界面,篩選功能通過picker組件控制,選擇后重置當前界面的數組,使得當前界面的信息發生改變
score.wxml
1 <picker mode="selector" bindchange="bindPickerChange" value="{{index}}" range="{{array}}"> 2 <view class="button" >篩選</view> 3 </picker>
score.js
1 data: { 2 array: ['全部', '增加', '減少'], //綁定在選擇器的數據 3 objectArray: [ 4 { 5 id: 0, 6 name: '全部' 7 }, 8 { 9 id: 1, 10 name: '增加' 11 }, 12 { 13 id: 2, 14 name: '減少' 15 } 16 ], 17 index: 0 //當前所選的條目的下標 18 },
1 bindPickerChange: function (e) { 2 console.log('picker發送選擇改變,攜帶值為', e.detail.value) 3 this.setData({ 4 index: e.detail.value //綁定選擇的下標 5 }) 6 if(e.detail.value==0) //下標為0則全選,將完整的數組賦值給當前 7 { 8 this.setData({ 9 score:app.globalData.score 10 }) 11 }else if(e.detail.value==1){ //下標為1,選擇增加積分的頁面 12 var i; 13 var temp=[]; 14 for(i=0;i<app.globalData.score.length;i++) //遍歷數組,找出增值為正的值存入中間tmp數組 15 { 16 if(app.globalData.score[i].point>0){ 17 temp.push(app.globalData.score[i]); 18 } 19 } 20 this.setData({ 21 score:temp //修改為處理后的數組 22 }) 23 }else{ //檢索減少的值為同理 24 var i; 25 var temp=[]; 26 for(i=0;i<app.globalData.score.length;i++) 27 { 28 if(app.globalData.score[i].point<0){ 29 temp.push(app.globalData.score[i]); 30 } 31 } 32 this.setData({ 33 score:temp 34 }) 35 } 36 }
pages/shop/shop(積分商城):
通過wx:for將商品信息綁定至界面。點擊時將點擊的商品卡片對應的信息傳入函數,函數比較當前積分和商品所需積分,滿足需求彈出確認窗口,積分不足則彈出提示框
shop.wxml
1 <view class="card-group" > 2 <view class="card" wx:for="{{shop}}" wx:key="{{item.index}}" bindtap="buy" data-item="{{item}}"> 3 <image class="img" src="{{item.src}}"> 4 </image> 5 <view class="title"> 6 {{item.title}} 7 </view > 8 <view class="score"> 9 {{item.point}}積分 10 </view> 11 </view>
shop.js
1 buy(e){ 2 var good = e.currentTarget.dataset.item; //獲得當前商品信息 3 if(good.point>=app.globalData.scorenum) //比較積分是否滿足 4 { 5 wx.showToast({ //積分不足,彈出純文字信息 6 title: '積分不足', 7 icon: 'none', //如果要純文本,不要icon,將值設為'none' 8 duration: 2000 9 }) 10 }else{ 11 let that = this; //保存當前page信息,在后續回調函數中this將無法調用 12 wx.showModal({ //確認框 13 title:"確認", 14 content:"將扣除500積分,您確定嗎?", 15 success:function(res){ //確認兌換,扣除積分 16 if(res.confirm){ 17 app.globalData.scorenum-=good.point; 18 19 that.setData({ 20 score:that.data.score-good.point 21 }) 22 wx.showToast({ 23 title: '兌換成功', 24 icon: 'none', 25 duration: 1000 26 }) 27 28 var newprice={ 29 available:0, 30 count:1, 31 money:3, 32 name:"可樂滿3減1券", 33 day:"2020.1.1-2021.1.1可用" 34 } 35 app.globalData.price.push(newprice); //把兌換的券加入券的數組 36 37 var newpoint={ 38 day: util.formatTime(new Date()), 39 title:"兌換商品", 40 point:-500 41 } 42 app.globalData.score.unshift(newpoint); //吧兌換的積分信息加入積分信息的數組 43 app.globalData.pricenum+=1; 44 } 45 else if(res.cancel){ 46 wx.showToast({ //取消兌換,彈出信息 47 title: '已經取消', 48 icon: 'none', //如果要純文本,不要icon,將值設為'none' 49 duration: 1000 50 }) 51 }} 52 }) 53 } 54 },
收獲總結
雖然是軟件工程作業的第一份作業,也着實花了不少功夫,從0基礎到完成一份較為完善的小demo,一步步查找文檔和資料,將一個個功能完善。其中也經過了不少的彎路,犯了不少錯誤。希望在今后的編碼中,可以吸取這次開發的經驗,將這次寫demo的經驗用在之后的大作業和編碼中。同時,可以繼續保持認真學習,自主學習的態度,同時向周圍優秀的同學學習,繼續完善持續跟進軟件工程的學習。