今天小帅逛哔哔哩哩看到一个todolist案例用的父子组件写的,小帅一时来了兴趣,手写了一个兄弟组件的todolist!!!!
首先兄弟组件要挂载一个$bus 当然名字随便起
main.js里的配置
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this
},
}).$mount('#app')
App.vue配置
<template>
<div>
<UserAdd />
<UserTodos />
<UserFooter />
</div>
</template>
<script>
import UserAdd from './components/UserAdd.vue';
import UserTodos from './components/UserTodos.vue';
import UserFooter from './components/UserFooter.vue';
export default {
name: 'TodoslistApp',
components: {
UserAdd,
UserTodos,
UserFooter,
},
data() {
return {
};
},
mounted() {
},
methods: {
},
};
</script>
<style lang="scss" scoped>
</style>
回车添加内容的组件userAdd.vue
<template>
<div>
<input type="text" placeholder="请输入内容,按回车键添加" class="addition" @keyup.enter="add" v-model="matter">
</div>
</template>
<script>
import {nanoid} from 'nanoid'
export default {
name: 'TodoslistUserAdd',
data() {
return {
// 双向数据绑定输入框的关键字
matter: ""
};
},
mounted() {
},
methods: {
// 键盘事件添加
add() {
// 定义添加的内容
let obj = { id:nanoid(), name: this.matter, checked: false }
// $emit派发
this.$bus.$emit('obj', obj)
// 添加之后清空输入框
this.matter = ''
}
},
};
</script>
<style lang="scss" scoped>
.addition {
width: 350px;
height: 25px;
outline: 0;
margin-left: 40px;
}
</style>
单个的内容组件userTodo.vue
<template>
<div>
<li>
<div>
<input type="checkbox" :checked="item.checked" @change="Multi(item)">
<span>{{ item.name }}</span>
</div>
<div>
<button @click="del(item.id)">删除</button>
</div>
</li>
</div>
</template>
<script>
export default {
name: 'TodoslistUserTodo',
// 接收父组件传过来的数据
props: {
item: {
type: Object,
required: true
}
},
data() {
return {
};
},
mounted() {
},
methods: {
// 删除事件
del(id) {
// 派发事件通知父组件删除
this.$emit('del', id)
},
// 子传父派发事件
Multi(item) {
this.$emit('Multi', item)
}
},
};
</script>
<style lang="scss" scoped>
li {
width: 350px;
display: flex;
justify-content: space-between;
button {
background-color: red;
border: 0;
color: white;
display: none;
}
}
li:hover {
background-color: black;
color: white;
button {
display: block;
}
}
</style>
整个内容的组件userTodos.vue
<template>
<div>
<ul>
<UserTodo v-for="item in todoList" :key="item.id" :item="item" @del="del" @Multi="Multi" />
</ul>
</div>
</template>
<script>
import UserTodo from './UserTodo.vue';
export default {
name: 'TodoslistUserTodos',
components: {
UserTodo
},
data() {
return {
todoList: JSON.parse(sessionStorage.getItem('add')) || []
};
},
mounted() {
// 兄弟组件通信 $on监听派送来的数据 $bus挂载原型上的事件总线
this.$bus.$on('obj', (obj) => {
// 头部添加
this.todoList.unshift(obj)
// 本地存储
sessionStorage.setItem('add', JSON.stringify(this.todoList))
});
// $emit派发
this.$bus.$emit('all', this.todoList)
// 监听派发过来的数据 赋值
this.$bus.$on('empty', (todoList) => {
this.todoList = todoList
})
},
methods: {
// 父组件收到通知进行删除
del(id) {
// 过滤出想要的留下 不想要的丢掉
this.todoList = this.todoList.filter(item => {
return item.id !== id
})
// 监听
this.$bus.$emit('arr', this.todoList)
// 更新本地
sessionStorage.setItem('add', JSON.stringify(this.todoList))
},
// 点击复选
Multi(item) {
item.checked = !item.checked
sessionStorage.setItem('add', JSON.stringify(this.todoList))
}
},
};
</script>
<style lang="scss" scoped>
ul {
list-style: none;
}
</style>
底部组件userFooter.vue
<template>
<div class="footer">
<div>
<input type="checkbox" v-model="all">
<span>已完成
<span>
{{ this.arr }}
</span>
/全部
<span>
{{ this.todoList.length }}
</span>
</span>
</div>
<div>
<button @click="empty">
清空已完成的任务
</button>
</div>
</div>
</template>
<script>
export default {
name: 'TodoslistUserFooter',
data() {
return {
todoList: JSON.parse(sessionStorage.getItem('add')) || [],
// 已完成的长度
arr: ''
};
},
mounted() {
},
created() {
// 兄弟组件通信 监听传过来的数据
this.$bus.$on('all', (todoList) => {
// 赋值
this.todoList = todoList
sessionStorage.setItem('add', JSON.stringify(this.todoList))
})
},
methods: {
// 清空已完成的
empty() {
this.todoList = this.todoList.filter(item => {
return !item.checked
})
// 清空完成的数据派发给兄弟组件
this.$bus.$emit('empty', this.todoList)
sessionStorage.setItem('add', JSON.stringify(this.todoList))
}
},
computed: {
// 全选事件
all: {
// 获取
get() {
// 监听
this.$bus.$on('arr', (obj) => {
this.todoList = obj
})
// 已完成的长度
this.arr = this.todoList.filter(item => {
return item.checked
}).length
// 判断数组的长度
if (this.todoList.length) {
// 迭代
return this.todoList.every(item => {
// 返回状态
return item.checked
})
}
},
// 设置
set(val) {
// 遍历每一项
this.todoList.forEach(item => {
item.checked = val
})
sessionStorage.setItem('add', JSON.stringify(this.todoList))
}
}
}
};
</script>
<style lang="scss" scoped>
.footer {
width: 350px;
margin-top: 10px;
display: flex;
justify-content: space-between;
margin-left: 40px;
button {
background-color: red;
border: 0;
color: white;
}
}
</style>