一.先写静态页面,然后把静态页面分组件划分,最后再写效果,效果有增删改查。
二.效果展示:
三.代码展示:
todos.css:
*{
padding: 0;
margin: 0;
}
ul,ol,li{
list-style: none;
}
body{
background-color: #F5F5F5;
}
#app{
width: 550px;
margin: 10px auto;
}
.title{
height: 150px;
line-height: 150px;
color: #EAD7D7;
font-size: 80px;
font-weight: bold;
text-align: center;
width: 100%;
}
.con{
width: 100%;
background-color: #fff;
}
.top{
width: 100%;
position: relative;
display: flex;
background-color: #fff;
align-items: center;
border-bottom: 1px solid #E6E6E6;
}
#inp{
width: 100%;
padding-left: 40px;
box-sizing: border-box;
height: 40px;
outline: none;
border: 0;
margin: 10px 0;
color: #E6E6E6;
font-size: 16px;
}
.select{
position: absolute;
width: 40px;
height: 40px;
margin: 10px 0;
color: #999;
text-align: center;
line-height: 40px;
font-weight: 600;
font-size: 24px;
transform: rotate(90deg);
}
.selbol{
color: #333;
}
.center{
width: 100%;
}
.list li{
width: 100%;
height: 40px;
border-bottom: 1px solid #E6E6E6;
display: flex;
align-items: center;
background-color: #fff;
justify-content: center;
border-bottom: 1px solid #E6E6E6;
}
.choose{
background: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E') no-repeat center;
background-size: 24px 24px;
width: 40px;
height: 40px;
}
.info{
height: 40px;
line-height: 40px;
color: #4d4d4d;
font-size: 16px;
flex: 1;
}
.list .checked .choose{
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}
.list .checked .info{
text-decoration: line-through;
color: #d9d9d9;
}
.delete{
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
margin-right: 10px;
color: red;
}
.bottom{
width: 100%;
height: 30px;
display: flex;
align-items: center;
}
.count{
width: 80px;
margin-left: 20px;
height: 30px;
line-height: 30px;
color: #999;
}
.tab{
height: 30px;
margin-left: 30px;
display: flex;
align-items: center;
}
.tabBox{
padding:0 5px ;
height: 20px;
line-height: 20px;
color: #999;
margin: 0 5px;
border: 1px solid transparent;
}
.tabSelect{
border-color: #999;
}
.clear{
height: 20px;
line-height: 20px;
margin-left: 50px;
color: #999;
}
组件:
TopVote.vue:
<template>
<div class="top">
<input type="text" placeholder="What needs to be done?" id="inp" :value='value' @input="$emit('input',$event.target.value)" @keyup.enter='$emit("addEvent")'>
<div :class=" {'select':true,'selbol':boo}" @click='$emit("booEvent")'> > </div>
</div>
</template>
<script>
export default {
props:['value','boo']
}
</script>
CenterVote.vue:
<template>
<div class="center">
<ul class="list">
<li
v-for="(item, index) in showList"
:class="{ checked: item.finished }"
:key="item.id"
@mouseover="item.show = true"
@mouseout="item.show = false"
>
<div class="choose" @click="$parent.one(item)"></div>
<div class="info">{{ item.value }}</div>
<div class="delete" v-show="item.show" @click="$parent.delet(index)">X</div>
</li>
</ul>
</div>
</template>
<script>
export default {
props:['showList']
}
</script>
BottomVote.vue:
<template>
<div class="bottom">
<div class="count">
<span class="num">{{ $parent.numbe }}</span> item left
</div>
<div class="tab">
<div
:class="{ tabBox: true, tabSelect: $parent.active == 'all' }"
@click="$parent.active = 'all'"
>
All
</div>
<div
:class="{ tabBox: true, tabSelect: $parent.active == 'no' }"
@click="$parent.active = 'no'"
>
Active
</div>
<div
:class="{ tabBox: true, tabSelect: $parent.active == 'yes' }"
@click="$parent.active = 'yes'"
>
Completed
</div>
</div>
<div class="clear" v-show="$parent.ssBoo" @click="$parent.clearAll">
Clear completed
</div>
</div>
</template>
<script>
export default ({
props:[]
})
</script>
Todos.vue:
<template>
<div>
<div class="title">TODOS</div>
<div class="con">
<TopVote :value="val" @input="change" @addEvent="add" @booEvent='booFn' :boo='boo'/>
<CenterVote :showList='showList'/>
<BottomVote :active='active'/>
</div>
</div>
</template>
<script>
import Vue from "vue";
import TopVote from "./TopVote.vue";
import CenterVote from "./CenterVote.vue";
import BottomVote from "./BottomVote.vue";
export default {
components: {
TopVote,
CenterVote,
BottomVote
},
data() {
return {
list: JSON.parse(localStorage.getItem("list")) || [],
showList: [],
// boo:false,
val: "",
active: "all",
// ssBoo:false
};
},
methods: {
add() {
//添加数据
if (this.val.trim() != "") {
this.list.push({
id: new Date().getTime(),
value: this.val,
finished: false,
show: false,
});
this.val = "";
}
},
change(value) {
this.val = value;
},
delet(index) {
//删除单个
this.list.splice(index, 1);
},
booFn(){
this.boo=!this.boo;
},
// all(){ //全选/反选
// this.boo=!this.boo;
// for(let item in this.list){
// this.list[item].finished=this.boo;
// }
// },
one(item) {
item.finished = !item.finished;
// let bol=true;
// for(let i in this.list){
// if(!this.list[i].finished){
// bol=false;
// break;
// }
// }
// this.boo=bol;
},
clearAll() {
this.list = this.list.filter((item) => {
return !item.finished;
});
},
},
watch: {
list: {
handler(value) {
if (this.active == "all") {
this.showList = value;
} else if (this.active == "no") {
this.showList = value.filter((item) => !item.finished);
} else {
this.showList = value.filter((item) => item.finished);
}
localStorage.setItem("list", JSON.stringify(value));
},
deep: true,
immediate: true,
},
active(value) {
if (value == "all") {
this.showList = this.list;
} else if (value == "no") {
this.showList = this.list.filter((item) => !item.finished);
} else {
this.showList = this.list.filter((item) => item.finished);
}
},
},
computed: {
numbe: {
//计算未完成数值
get() {
let num = 0;
this.list.map((item) => {
if (!item.finished) {
num++;
}
});
return num;
},
},
boo: {
//计算全选/反选
get() {
let bol = true;
for (let i in this.list) {
if (!this.list[i].finished) {
bol = false;
break;
}
}
return bol;
},
set(value) {
for (let item in this.list) {
this.list[item].finished = value;
}
},
},
ssBoo: {
//批量删除是否隐藏
get() {
let shows = this.list.some((item) => {
return item.finished;
});
return shows;
},
},
},
};
</script>
App.vue:
<template>
<div id="app">
<todos />
</div>
</template>
<script>
import Todos from "./components/Todos.vue";
export default {
name: "App",
components: {
Todos,
},
};
</script>
<style lang="scss">
@import url("assets/todos.css");
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
#app {
// font-size: 40px;
text-align: center;
color: #2c3e50;
}
</style>
main.js:
// 引入vue
// import Vue from 'vue/dist/vue'
import Vue from 'vue'
// 引入App组件 是所有组件的父组件
import App from './App.vue'
// import "./assets/demo"
import "bootstrap/dist/css/bootstrap.css"
// 关闭vue的生产提示
Vue.config.productionTip = false
// 创建vue实例
new Vue({
render: h => h(App),
// render(createElement){
// return createElement('h1','标题')
// }
// template:'<h2>标题</h2>'
}).$mount('#app')
本篇文章主要讲述了用vue实现todos效果,有代码展示,欢迎观看!!!