使用vue重构ToDoList—最简单的待办事项列表
大家好,我是一个刚入门前端的一个小白,希望各位大佬们能够对小的多多指导,我先做一下自我介绍吧。我叫王小辉,我大学的专业是播音主持,为什么选择学习前端呢,这就跟我大学最后一年跟几个小伙伴一起创业开始说起,其实也不能完全说成创业,其实就是大学期间认识的几个小伙伴想一起做一些喜欢的事情,那是18年年初,当时小程序市场起步,市场上大大小小的小程序公司如雨后春笋冒出来,当时我们觉得这个小程序是一个市场,并且可以通过大学生创业这个方式获取到一些资源。我的另两个小伙伴分别是商学院和艺术设计学院的,我们当时没有一个人懂得技术,所以我们就了解到了,一些大的互联网公司做的小程序可以代理,可以开代理商后台的,我们当时拿着三千以大学生创业的身份跟广州的一家小程序公司谈,最后谈了下来,基本一个模版都在300-1000左右的拿货价,接下来我们就开始了漫长的推广过程,刚好当时赶到暑假,临时招募学校里的几位同学加入我们,公司的运营总共持续了5个月左右,总共谈下2位代理,8个客户,共计收到打款十多万。感觉自己扯的有点远了,继续说回为什么想要学习编程,就是因为在我们业务的过程中遇到了很多的难题,模版的功能是固定的,客户的需求无法满足,给当时的我们造成很多的困扰,所以当时就萌生了这个想法,当时也尝试着学习一些基础的页面的东西,尝试去满足客户需求,但是对于一个什么都不动的文科生,实在是太难了。但是前端时间因为疫情所以决心转变一下,当时也是考虑很久,对前端也比较感兴趣。其他废话就不说了,最近学到vue,做了一个作业,在这里分享出来,希望大佬指点一下,哪里需要改进,请不吝赐教。
先来分享一下已经打包上线的demo
ToDoList-代办事项列表
地址:http://todolist.wyhvip.top/#/
为了练习数据流,我总共分成了三个组件
其实最后两个组件逻辑相似,其实是可以和在一起的,这样可以节省很多代码段
下面这个Home是主组件
<template>
<div class="home">
<header>
<div class="banxin">
<label for="textval">ToDoList</label>
<input
type="text"
placeholder="添加ToDo"
id="textval"
v-model.trim="userval"
@keyup.enter="submit"
/>
</div>
</header>
<section class="banxin">
<div class="title">
<h2>正在进行</h2>
<span>{{goingArr.length}}</span>
</div>
<ul-comp
:goingarr="goingArr"
@goingtogdown="fathergoingtogdown"
@delgoingarr="fatherdelgoingarr"
@goingtoginphdiv="fathergoingtoginphdiv"
@xggoingarrs="fatherxggoingarrs"
></ul-comp>
</section>
<section class="banxin">
<div class="title">
<h2>已经完成</h2>
<span>{{doneArr.length}}</span>
</div>
<ol-comp
:donearr="doneArr"
@donetogup="fatherdonetogup"
@deldonearr="fatherdeldonearr"
@donetoginphdiv="fatherdonetoginphdiv"
@xgdonegarrs="fatherxgdonegarrs"
></ol-comp>
</section>
<footer>
Copyright © 2020 todolist.wyhvip.top
<a @click="createlocalstorage">clear</a>
</footer>
</div>
</template>
<script>
// @ is an alias to /src
import UlComp from "../components/UlComp.vue";
import OlComp from "../components/OlComp.vue";
export default {
name: "Home",
components: {
UlComp,
OlComp
},
data() {
return {
userval: "",
num: 0,
goingArr: [],
doneArr: []
};
},
created() {
this.num = JSON.parse(localStorage.getItem("num")) || 0;
this.goingArr = JSON.parse(localStorage.getItem("goingArr")) || [];
this.doneArr = JSON.parse(localStorage.getItem("doneArr")) || [];
},
methods: {
fathergoingtogdown(i) {
this.goingArr[i].ifShowIpu = false;
this.goingArr[i].ifCheck = true;
this.doneArr.unshift(this.goingArr[i]);
this.goingArr.splice(i, 1);
this.setlocalstorage();
},
fatherdonetogup(i) {
this.doneArr[i].ifShowIpu = false;
this.doneArr[i].ifCheck = false;
this.goingArr.push(this.doneArr[i]);
this.doneArr.splice(i, 1);
this.setlocalstorage();
},
fatherdelgoingarr(i) {
this.goingArr.splice(i, 1);
this.setlocalstorage();
},
fatherdeldonearr(i) {
this.doneArr.splice(i, 1);
this.setlocalstorage();
},
fathergoingtoginphdiv(i) {
this.goingArr[i].ifShowIpu = true;
this.setlocalstorage();
},
fatherdonetoginphdiv(i) {
this.doneArr[i].ifShowIpu = true;
this.setlocalstorage();
},
submit() {
if (this.userval == "") {
return;
} else {
this.num++;
let obj = {
id:
this.num < 10
? "00" + this.num
: this.num < 100
? "0" + this.num
: "" + this.num,
ifCheck: false,
ifShowIpu: false,
content: this.userval
};
this.goingArr.unshift(obj);
this.userval = "";
this.setlocalstorage();
}
},
setlocalstorage() {
localStorage.setItem("num", this.num);
localStorage.setItem("goingArr", JSON.stringify(this.goingArr));
localStorage.setItem("doneArr", JSON.stringify(this.doneArr));
},
fatherxggoingarrs(i) {
this.goingArr[i].ifShowIpu = false;
this.setlocalstorage();
},
fatherxgdonegarrs(i) {
this.doneArr[i].ifShowIpu = false;
this.setlocalstorage();
},
createlocalstorage() {
localStorage.clear();
this.goingArr = [];
this.doneArr = [];
}
}
};
</script>
<style>
* {
margin: 0;
padding: 0;
border: 0;
list-style: none;
}
body {
background-color: #cdcdcd;
font-size: 16px;
}
.banxin {
width: 600px;
margin: 0 auto;
}
header {
min-width: 600px;
height: 50px;
background: rgba(47, 47, 47, 0.98);
}
label {
float: left;
width: 100px;
line-height: 50px;
color: #ddd;
font-size: 24px;
cursor: pointer;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
header input {
float: right;
width: 60%;
height: 24px;
margin-top: 12px;
text-indent: 10px;
border-radius: 5px;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24),
0 1px 6px rgba(0, 0, 0, 0.45) inset;
border: none;
outline: none;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
}
.title h2 {
font-size: 24px;
color: #000;
margin: 20px 0;
}
.title span {
display: inline-block;
padding: 0 5px;
height: 20px;
border-radius: 20px;
background: #e6e6fa;
line-height: 22px;
text-align: center;
color: #666;
font-size: 14px;
}
.list li {
height: 32px;
line-height: 32px;
background: #fff;
margin-bottom: 10px;
border-radius: 3px;
border-left: 5px solid #629a9c;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07);
display: flex;
justify-content: space-around;
align-items: center;
cursor: grabbing;
}
.list li .fxk {
width: 22px;
height: 22px;
cursor: pointer;
margin: 3px 3px 3px 4px;
margin-left: 10px;
}
.list li .txt {
width: 421px;
height: 24px;
padding: 1px 2px;
border-radius: 5px;
text-indent: 1em;
font-size: 16px;
color: #000;
/* outline: none; */
outline-color: #999;
cursor: progress;
}
.list li div {
width: 421px;
height: 32px;
padding: 1px 2px;
text-indent: 1em;
font-size: 16px;
color: #000;
}
.list li label {
width: 100px;
height: 32px;
}
.list li a {
float: right;
text-decoration: none;
width: 14px;
height: 12px;
border-radius: 14px;
border: 6px double #fff;
background: #ccc;
line-height: 14px;
text-align: center;
color: #fff;
font-weight: bold;
font-size: 14px;
cursor: pointer;
margin-right: 5px;
}
.ollist li {
border-left: 5px solid #999;
opacity: 0.5;
cursor: progress;
}
footer {
font-size: 14px;
color: #666;
text-align: center;
display: block;
margin-top: 20px;
margin-bottom: 30px;
}
footer a {
text-decoration: none;
font-size: 14px;
color: #999;
cursor: pointer;
}
</style>
下面就是正在进行的组件和已完成的组件
正在进行组件
<template>
<ul class="list">
<li v-for="(item,i) in goingarr" :key="item.id">
<input :checked="item.ifCheck" type="checkbox" class="fxk" @click="togdwon(i)" />
<input
v-focus
v-if="item.ifShowIpu"
type="text"
class="txt"
:id="item.id"
v-model="item.content"
@keyup.13="xggoingarr(i)"
@blur="blurIpu(i)"
/>
<div v-else @click="toginphdiv(i)">{{item.content}}</div>
<label :for="item.id" @click="toginphdiv(i)"></label>
<a @click="dellist(i)">-</a>
</li>
</ul>
</template>
<script>
export default {
props: ["goingarr"],
methods: {
togdwon(i) {
this.$emit("goingtogdown", i);
},
dellist(i) {
this.$emit("delgoingarr", i);
},
toginphdiv(i) {
this.$emit("goingtoginphdiv", i);
},
xggoingarr(i) {
this.$emit("xggoingarrs", i);
},
blurIpu(i) {
this.$emit("xggoingarrs", i);
}
},
directives: {
focus: {
inserted(el) {
el.focus();
}
}
}
};
</script>
<style>
</style>
已经完成的组件
<template>
<ol class="list ollist">
<li v-for="(item,i) in donearr" :key="item.id">
<input :checked="item.ifCheck" type="checkbox" class="fxk" @click="togup(i)" />
<input
v-focus
v-if="item.ifShowIpu"
type="text"
class="txt"
:id="item.id"
v-model="item.content"
@keyup.13="xgdonegarr(i)"
@blur="blurIpu(i)"
/>
<div v-else @click="toginphdiv(i)">{{item.content}}</div>
<label :for="item.id" @click="toginphdiv(i)"></label>
<a @click="dellist(i)">-</a>
</li>
</ol>
</template>
<script>
export default {
props: ["donearr"],
methods: {
togup(i) {
this.$emit("donetogup", i);
},
dellist(i) {
this.$emit("deldonearr", i);
},
toginphdiv(i) {
this.$emit("donetoginphdiv", i);
},
xgdonegarr(i) {
this.$emit("xgdonegarrs", i);
},
blurIpu(i) {
this.$emit("xggoingarrs", i);
}
},
directives: {
focus: {
inserted(el) {
el.focus();
}
}
}
};
</script>
<style>
</style>