【Vue】第十部分 任务清单小案例
10. 任务清单案例
main.js
import Vue from "vue"
import App from "./App.vue"
Vue.config.productionTip = false //阻止vue在生成时自动产生提示
new Vue({
el: '#app',
data: {
},
beforeCreate(){
Vue.prototype.$bus = this //绑定事件总线
},
render: h => h(App)
})
App.vue
<template>
<div class="wrapper">
<MyTop @addTodo="addTodo"/>
<MyContent :plans="plans" />
<MyBottom :plans="plans" @selectAll="selectAll" @clearTodo="clearTodo"/>
</div>
</template>
<script>
import MyTop from "./components/MyTop.vue"
import MyBottom from "./components/MyBottom.vue"
import MyContent from "./components/MyContent.vue"
export default {
name:"App",
components:{MyTop,MyBottom,MyContent},
data(){
return{
// []保证在没有值的时候可以读到length的值为0
plans:JSON.parse(localStorage.getItem("plan")) || []
}
},
watch:{
plans:{
handler(val){
localStorage.setItem("plan",JSON.stringify(val))
},
// 开启深层次监视,不然改对象里的属性watch检测不到
deep:true
}
},
methods:{
// 添加任务
addTodo(val){
this.plans.unshift(val)
},
// 获取计划是否执行
select(id){
this.plans.filter((ele)=>{
if(ele.id === id)
return ele.complete = !ele.complete
})
},
// 删除指定计划
delTodo(id){
/*
filter返回的是一个全新的数组但是不会破坏原数组
所以想要改变就的重新赋值
*/
this.plans = this.plans.filter((ele)=>{
return ele.id !== id
})
},
//全选和全不选
selectAll(flag){
this.plans.forEach((ele)=>{
ele.complete = flag
})
},
// 清除已经完成的任务
clearTodo(){
this.plans = this.plans.filter((ele)=>{
return !ele.complete
})
},
//编辑内容
editData(id,value){
this.plans.forEach((ele)=>{
if(ele.id == id)
{
ele.name = value
}
})
}
},
mounted(){
this.$bus.$on("select",this.select)
this.$bus.$on("delTodo",this.delTodo)
this.$bus.$on("edit",this.editData)
}
}
</script>
<style>
*{
padding: 0;
margin: 0;
}
.wrapper
{
width: 600px;
outline: 1px solid rgb(133, 133, 133) ;
border-radius: 10px;
margin: 100px auto;
padding-top: 20px;
box-sizing:border-box;
}
</style>
其他的子组件我放在components文件夹中,我将其拆分成四个部分
components
—MyTop.vue //顶部
—MyItem.vue //每一条list
—MyContent.vue //包裹list
—MyBottom.vue //底部的组件
MyTop.vue
<template>
<div class="top-wrapper">
<input type="text" placeholder="请输入需要添加的任务" @keyup.enter="addPlan" v-model="val">
</div>
</template>
<script>
// 导入nanoid,这是个随机生成不重复值的包
import { nanoid } from "nanoid"
export default {
name:"Top",
data(){
return{
val:""
}
},
methods:{
addPlan(){
if(this.val.trim())
{
const wrapper = {id:nanoid(),name:this.val,complete:false}
this.$emit("addTodo",wrapper)
this.val = ""
}
}
},
}
</script>
/*
scoped表示该样式为该组件的样式,避免了类名冲突问题
- 但是发现父子组件是没有办法避免的,因为子组件会得到
父组件的类名所以没有办法解决类名冲突问题.
- 该属性如果给App使用那就变成只能App所有的样式给他自己使用
造成样式出现问题,所以并不适合使用
*/
<style scoped>
.top-wrapper{
width: 550px;
height: 50px;
margin: 0 auto;
}
.top-wrapper input{
width: 550px;
height: 30px;
font-size: 18px;
outline: none;
border: 1px solid black;
padding-left: 8px;
box-sizing: border-box;
}
.top-wrapper input:focus{
border: 1px solid rgb(75, 75, 75);
box-shadow: 0 0 4px rgb(75,75,75);
}
</style>
MyItem.vue
<template>
<li class="it-wrapper" >
<input type="checkbox" :checked = planobj.complete @click="negation">
<span v-show="!planobj.isEdit">{{planobj.name}}</span>
<input type="text"
v-show="planobj.isEdit"
:value="planobj.name"
@blur="cancel(planobj,$event)"
ref="inp">
<button class="btn" @click="del">删除</button>
<button class="btn1" @click="edit(planobj)">编辑</button>
</li>
</template>
<script>
export default {
name:"MyItem",
props:["planobj"],
methods:{
negation(){
this.$bus.$emit("select",this.planobj.id)
},
del(){
if(confirm("确定要删除 "+this.planobj.name +" 任务"))
{
this.$bus.$emit("delTodo",this.planobj.id)
}
},
edit(planobj){
this.$set(planobj,"isEdit",true)
this.$nextTick(function(){
this.$refs.inp.focus()
})
},
cancel(planobj,e){
planobj.isEdit = false
this.$bus.$emit("edit",planobj.id,e.target.value)
}
}
}
</script>
<style scoped>
.it-wrapper{
list-style: none;
height: 40px;
width: 550px;
line-height: 40px;
padding-left: 12px;
border: 1px solid #bbb;
border-bottom: none;
box-sizing: border-box;
position: relative;
}
.it-wrapper:hover
{
background-color:rgba(187, 187, 187, 0.301) ;
}
.it-wrapper:hover .btn,.it-wrapper:hover .btn1
{
display: block;
}
.it-wrapper span{
padding-left: 8px;
font-size: 16px;
}
.btn,.btn1{
border: none;
width: 60px;
height: 30px;
color: aliceblue;
border-radius: 5px;
position: absolute;
outline: none;
background-color: #f04b4b;
top: 50%;
right:3px;
transform: translateY(-50%);
display: none;
}
.btn:hover{
background-color: #cc4040;
}
.btn1:hover{
background-color: rgb(43, 173, 224);
}
.btn1{
background-color: rgb(41, 194, 255);
right: 75px;
}
</style>
MyContent.vue
<template>
<div class="con-wrapper">
<MyItem
v-for="planobj in plans"
:key="planobj.id"
:planobj="planobj"
/>
</div>
</template>
<script>
import MyItem from "./MyItem.vue"
export default {
name:"MyContent",
components:{MyItem},
props:["plans"]
}
</script>
<style scoped>
.con-wrapper{
width: 550px;
margin: 0 auto;
}
</style>
总结
以上就是今天要讲的内容,大家也可以亲自动手写一写!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82954.html