1.前言
- 从两周前开始接触小程序,到现在也学到了一点.准备通过本次的文章,来从0到1写一个简单的单机版小程序,来帮助一些准备入门小程序开发的同学,同时也算是对自己这两周学习小程序的一个巩固与检测
- 后续我也会在我的博客更新一些小程序的学习与'讲解',与小伙伴们共同学习
- 最后会布置一个简短的小作业,同学们可以自己去补充
2.看前必读
- 本文章并非针对于0基础,像工具的一些用法,目录结构不会讲解太多,有不会的可以找我咨询,博客上有我的联系方式,本文章主要是通过从0到1写一个简单的单机小程序,主要是一些js语法,css样式等的解释与学习
- 当然会贴上一些官方的链接供大家去参考
- 微信小程序官网 注册账号,选择小程序,根据指引来就可以:
- 微信小程序开发工具 自助安装根据指引打开
- 在开始之前,向大家推荐一个非常不错的技术公众号和小程序,每天会推荐一些优质文章来供大家学习,微信搜索公众号和小程序 码个蛋
3.简单准备工作
- 先看一下小程序的基础结构,不会画图,将就看吧,三个页面,具体一些比较细的效果没有画出来
- 一些弹窗按钮后续再补充吧,本文章会根据这个模型来写一个简单的单机小程序
- 简单的目录讲解 js是写一些函数和一些逻辑,wxml是页面设计,wxss是样式编辑,json是当前page的一些配置
4. 正式开始(在实际写的时候与上面效果图不太相同)
4.1首页布局
先看下我的具体实现效果图
先分析一下首页的功能
- 需要获取到当前用户的微信头像和微信昵称
- 获取今日未打卡状态
- 点击打卡要记录今天的打卡状态
- 打卡按钮根据打卡状态变更样式
1.wxml布局代码
<!--pages/index/index.wxml-->
<view>
<!-- 最顶部样式 -->
<view class="top-view">
<!-- 头像与昵称 -->
<view class="user-info">
<!-- 头像 -->
<view class="avatar">
<open-data type="userAvatarUrl"></open-data>
</view>
<!-- 昵称 -->
<view class="nickname">
<open-data type="userNickName"></open-data>
</view>
</view>
<!-- 打卡天数统计 -->
<view class="day-count">
<text>
已累计打卡
</text>
<text class="day-count-num">
{{listSize}}
</text>
<text>
天
</text>
</view>
</view>
<!-- 底部view -->
<view class="bottom-view">
<view bindtap="punchTheClock" class="btn_click">
<text>{{todayClick?'已打卡':'今日打卡'}}</text>
</view>
<view bindtap="jumpDetail" class="btn_detail">打卡详情</view>
</view>
</view>
2.样式代码
/* pages/index/index.wxss */
.top-view {
position: relative;
width: 100%;
height: 280rpx;
background-color: #FFFF00;
}
.user-info {
left: 50rpx;
position: relative;
top: 80rpx;
display: flex;
flex-direction: row;
align-items: center;
}
.avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
overflow: hidden;
}
.nickname {
margin-left: 30rpx;
font-size: 38rpx;
color: #000000;
}
.day-count {
position: absolute;
right: 20rpx;
bottom: 20rpx;
display: flex;
}
.day-count-num {
color: #FF0000;
}
.bottom-view {
display: flex;
flex-direction: column;
align-items: center;
scrollbar-shadow-color: #FF0000;
}
.btn_click {
border-radius: 50%;
overflow: hidden;
background-color: #FF0000;
display: flex;
width: 300rpx;
margin-top: 280rpx;
box-shadow: 0px 2px 5px 5px #FF0000;
align-items: center;
justify-content: center;
height: 300rpx;
}
.btn_click text {
color: #FFFFFF;
font-size: 60rpx;
}
.btn_detail {
display: flex;
align-items: center;
justify-content: center;
font-size: 45rpx;
color: #000000;
position: absolute;
bottom: 100rpx;
}
3.js逻辑代码层
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
todayClick: false,
clickStatusKey: '',
clickListKey: 'clickListKey',
clickList: [],
listSize: '0'
},
/**
* 点击打卡
*/
punchTheClock() {
if (this.data.todayClick) {
//如果今天已打卡
} else {
wx.setStorageSync(this.data.clickStatusKey, true)
let itemData = {
date: this.getNowDate(),
// date: '2021-7-10',
status: true,
desc: ''
}
this.getTodayClickStatus()
let clickList = this.getClickList()
this.setData({
clickList: clickList
})
this.data.clickList.unshift(itemData)
wx.setStorageSync(this.data.clickListKey, this.data.clickList)
this.getClickDayCount()
}
},
getClickList() {
return wx.getStorageSync(this.data.clickListKey) || []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
clickStatusKey: 'clickStatus_' + this.getNowDate()
})
this.getTodayClickStatus()
},
/**
* 获取今天的打卡状态
*/
getTodayClickStatus() {
let status = wx.getStorageSync(this.data.clickStatusKey)
if (status != null) {
this.setData({
todayClick: status
})
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
this.addUnPunchDay()
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.getClickDayCount()
},
/**
* 添加未打卡日期数据
*/
addUnPunchDay() {
//当前添加的日期
let currentAddDate = ''
let list = wx.getStorageSync(this.data.clickListKey) || []
if (list.length == 0 || list[0].date == this.getNowDate()) {
//从未打过卡或者最后一个打卡的是昨天
return
}
currentAddDate = list[0].date
//一直添加直到添加到昨天
while (true) {
if (currentAddDate >= this.getNowDate()) {
return
}
currentAddDate = this.getAppointDayDate(currentAddDate, 1)
//所有status为false,没打卡状态
let itemData = {
date: currentAddDate,
status: false,
desc: ''
}
//倒序把距离上一次打开的每一天都添加上
list.unshift(itemData)
if (currentAddDate == this.getAppointDayDate(this.getNowDate(), -1)) {
console.log("添加到昨天之后跳出循环")
break
}
}
wx.setStorageSync(this.data.clickListKey, list)
},
/**
* 获取指定日期的前几天或者后几天
* day: -1前一天 1后一天
*/
getAppointDayDate(date, day) {
var dd = new Date(date);
dd.setDate(dd.getDate() + day);
var y = dd.getFullYear();
var m = dd.getMonth() + 1 < 10 ? "0" + (dd.getMonth() + 1) : dd.getMonth() + 1;
var d = dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate();
return y + "-" + m + "-" + d;
},
/**
* 获取真正的打卡天数
*/
getClickDayCount() {
let clickList = this.getClickList()
let clickSize = 0
for (let index = 0; index < clickList.length; index++) {
if (clickList[index].status) {
clickSize++
}
}
this.setData({
listSize: clickSize
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
// 获取当前日期
getNowDate: function () {
let dateTime
let YYYY = new Date().getFullYear()
let MM = new Date().getMonth() + 1
let DD = new Date().getDate()
dateTime = YYYY + '-' + MM + '-' + DD
return dateTime
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
jumpDetail() {
wx.navigateTo({
url: '../listdetail/listdetail',
})
}
})
4.2列表布局布局
先附上效果图
分析一下主要功能
- 首先要把距离上次日期的中间未打卡数据添加进来
- 根据打卡状态改变背景颜色和字体颜色
- 如果未打卡或者补卡的要显示注意按钮
- 如果是补卡的用户点击注意弹出未打卡的备注原因
- 点击未打卡跳到补卡页面
<!--pages/listdetail/listdetail.wxml-->
<view>
<!-- 空数据页面 -->
<view wx:if="{{isEmpty}}" class="empty-view">
<text>你还没有打过卡</text>
</view>
<block wx:else>
<!-- 有数据页面 -->
<view class="list-item-view" style="background-color: {{item.status?'#FFFF00':'#FF0000'}}" wx:for="{{punchList}}">
<view class="punch-info">
<view class="item-date" style="color: {{item.status?'#000000':'#FFFF00'}}">{{item.date}}</view>
<view class="item-status" style="color: {{item.status?'#FF0000':'#FFFFFF'}}">{{item.status?'已打卡':'未打卡'}}</view>
</view>
<view wx:if='{{!item.status||item.desc}}' class="view-desc">注意</view>
</view>
</block>
</view>
wxss样式页面
/* pages/listdetail/listdetail.wxss */
.list-item-view {
margin-top: 5rpx;
padding: 30rpx;
display: flex;
flex-direction: row;
background-color: #FFFF00;
align-items: center;
}
.punch-info {
display: flex;
flex-direction: column;
align-items: center;
}
.item-date{
font-weight: 600;
color: #000000;
}
.item-status{
font-size: 30rpx;
color: #FF0000;
}
.view-desc {
position: absolute;
right: 30rpx;
}
.item-line{
height: 2rpx;
background-color: #2b2a2a;
}
逻辑js页面
// pages/listdetail/listdetail.js
Page({
/**
* 页面的初始数据
*/
data: {
isEmpty: false,
punchList: [],
clickListKey: 'clickListKey'
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let list = wx.getStorageSync(this.data.clickListKey) || []
console.log(list)
this.setData({
punchList: list,
isEmpty: list.length <= 0
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
4.3补卡页面
- 给同学们留下的一个小作业,后续会在文章中补充
- 点击未打卡列表跳转该页面,正常打卡不可跳转
思路提示
- 将列表的index传入该页面,点击提交补卡,将该item的desc字段修改,然后关闭页面,备注不可少于10个字
- 返回上一页直接展示该数据,变更为已打卡状态
源码地址:微信打卡小程序