1.任务
学习了一些基础的vue后决定自己编写一个简易的打卡网页,实现了一些简单的功能
-
添加计划,用户输入计划,通过回车将计划加入,显示在网页中
-
每条计划,可通过点击按钮来进行打卡天数累加
- 实现每条计划的按钮一天只能点击一次用以打卡
- 多次点击多次提醒计划已完成
-
一条计划可通过双击计划确定是否删除
-
网页背景设置为模糊样式
2.代码实现
template
使用v-model、v-on、v-for等指令对数据的获取及操作非常的便捷
<template>
<div style="width:100%;overflow: hidden;" id="div2">
<div id="bg-blur"></div>
<div style="position: absolute;top: 0;width: 100%;" id="div1">
<center style="margin-top: 10px;">
<label>
<input type="text" v-model="text" :maxlength="15" placeholder="添加计划" @keyup.enter="addplan"/>
</label>
<table style="width: 50%;margin-top: 20px;" id="table">
<tbody>
<tr v-for="plan in plans" :key="plan.id" @dblclick="remove(plan.id)" id="tr">
<td style="width: 40%;">{{plan.plan}}</td>
<td style="width: 40%;">已完成 {{plan.count}} 天</td>
<td style="width: 20%;">
<button @click="finish(plan.id)">完成任务</button>
</td>
</tr>
</tbody>
</table>
</center>
</div>
</div>
</template>
script
使用了ant-design的一些组件来进行全局提醒,为了方便,暂时将数据存在了localStorage里。
在每一个plan对象里放了两个属性:today,yesterday,用来实现每天只能打卡一次。
<script>
import moment from 'moment'
export default {
data() {
return {
plans: JSON.parse(localStorage.getItem('plans')) || [],
text: ''
}
},
computed: {
plan() {
return {
id: Number(Math.random().toString().substr(3, length) + Date.now()).toString(36),
plan: this.text,
count: 0,
yesterday: '',
today: moment().format('yyyy/MM/DD')
}
}
},
created() {
this.plans.forEach(plan => {
plan.today = moment().format('yyyy/MM/DD')
})
},
mounted() {
this.setBody()
window.onresize = () => {
return (() => {
this.setBody()
})()
}
},
methods: {
height() {
const h1 = document.body.offsetHeight
const h2 = document.getElementById('div1').offsetHeight + 80
return h1 > h2 ? h1 : h2
},
width() {
const w1 = document.body.offsetWidth
const w2 = document.getElementById('tr').offsetWidth + 80
return w1 > w2 ? w1 : w2
},
setBody() {
document.getElementById("div2").style.height = this.height() + 'px'
document.getElementById("div2").style.width = this.width() + 'px'
},
addplan() {
if (this.text !== '') {
if (this.plans.length < 10) {
this.plans.push(this.plan)
this.setBody();
this.text = ''
localStorage.setItem('plans', JSON.stringify(this.plans))
} else {
alert('每天的计划不要太多哟')
this.text = ''
}
}
},
finish(id) {
this.plans.forEach(plan => {
if (plan.id === id) {
if (plan.today !== plan.yesterday) {
this.$message.success('恭喜你完成了今天的' + plan.plan)
plan.count++
plan.yesterday = plan.today
} else {
this.$message.info('今天已完成' + plan.plan + ',明天再来吧,再接再厉', 2)
}
}
})
localStorage.setItem('plans', JSON.stringify(this.plans))
},
remove(id) {
var result = confirm("确定要删除这条计划吗?");
if (result) {
this.plans = this.plans.filter(plan => plan.id !== id)
this.setBody()
localStorage.setItem('plans', JSON.stringify(this.plans))
}
}
}
}
</script>
style
<style>
html {
width: 100%;
height: 100%;
}
#bg-blur {
background: url('./assets/bg.gif');
height: 100%;
width: 100%;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
filter: blur(10px);
transform: scale(1.2);
}
input {
border: none;
border-bottom: 2px solid #80848f;
width: 40%;
height: 30px;
text-align: center;
outline: none;
font: 500 15px "微软雅黑 Light";
color: #1c2438;
background: none;
}
input:focus {
border-bottom: 2px solid #01AAED;
}
button {
border: none;
background-color: #ffffff;
outline: none;
width: 100px;
height: 40px;
color: #2F4056;
font: 500 16px "微软雅黑 Light";
border-radius: 8px;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1);
margin-left: 30px;
}
button:hover {
box-shadow: 0 0 10px #F0F0F0;
}
tr {
display: block;
border: 3px solid #4a677d;
border-radius: 8px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
margin-top: 5px;
}
td {
text-align: center;
padding: 10px 50px;
}
</style>
3.最后成果
网页地址:http://sangzican.3vkj.net(电脑打开效果更好)