todolist案例

今天小帅逛哔哔哩哩看到一个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>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮沉随浪逝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值