欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue 组件化综合案例demo

程序员文章站 2022-07-04 19:26:47
...

1. 技术栈

vue 组件化编码

父子组件数据交互 $parent

watch 深度监视

本地缓存 localstorage

js高阶函数灵活使用

按键修饰符使用

2. 编码
  1. app.vue

<template>
    <div class="todo-container">
        <Header></Header>
        <Todos :todos="todos"></Todos>
        <Footer></Footer>
    </div>
</template>

<script>
    import Header from "./components/header/Header";
    import Todos from "./components/todos/Todos";
    import Footer from "./components/footer/Footer";
    export default {
        data () {
          return {
              todos: JSON.parse(localStorage.getItem('todo'))
          }
        },
        // 深度监视 todos数据变化
        watch : {
          todos: {
              deep: true,
              handler (value) {
                  localStorage.setItem('todo', JSON.stringify(value))
              }
          }
        },
        components: {
            Header, Todos, Footer
        }
    }
</script>


<style lang="less">
    .todo-container{
        width: 500px;
        border: 1px solid #ccc;
        margin: auto;
        user-select: none;
    }
</style>

  1. header.vue
<template>
    <div class="header">
        <input type="text" placeholder="请添加任务" @keyup.enter="addTodo" v-model="currentTodo">
    </div>
</template>

<script>
    export default {
        name: "Header",
        data () {
            return {
                currentTodo: ''
            }
        },
        methods: {
            addTodo () {
                this.$parent.todos.unshift({name: this.currentTodo, complate: false});
                this.currentTodo = '';
            }
        }
    }
</script>

<style scoped lang="less">
    .header{
        width: 100%;
        height: 50px;
        border-bottom: 1px  solid #ccc;
        input{
            width: 100%;
            height: 100%;
            outline: none;
            border: 1px solid #ccc;
            padding: 20px;
            box-sizing: border-box;
        }
    }
</style>
  1. todos
<template>
    <div class="content">
        <div class="item" v-for="(item, index) in todos" :key="index">
            <input type="checkbox" :checked="item.complate" @click="item.complate = !item.complate">
            <span>{{ item.name }}</span>
            <button @click.prevent="deleteTodo(index)">删除</button>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Todos",
        props: ['todos'],
        data () {
          return {
              isShow: false
          }
        },
        methods: {
            deleteTodo (index) {
                this.$parent.todos.splice(index, 1)
            }
        }
    }
</script>

<style scoped lang="less">
    .content{
        width: 100%;
        .item{
            width: 100%;
            line-height: 40px;
            padding-left: 20px;
            border-bottom: 1px solid #ccc;
            position: relative;
            input{
                margin-right: 10px;
            }
            button{
                line-height: 20px;
                font-size: 14px;
                outline: none;
                border: 1px solid grey;
                background-color: red;
                color: white;
                position: absolute;
                right: 10px;
                margin-top: 10px;
            }
        }
    }
</style>

  1. footer
<template>
    <div class="bottom">
        <div class="selectAll">
            <input type="checkbox" id="select" @click="selectAll"> <label for="select"> 全选 / 全不选 </label>
        </div>

        <div class="complate">
            <span>已完成{{ complated }} / 总任务{{ $parent.todos.length }}</span>
        </div>

        <button @click="deleteComplated">清空已完成</button>
    </div>
</template>

<script>
    export default {
        name: "Footer",
        data () {
          return {
              isAllSelect : false
          }
        },
        methods: {
            selectAll () {
                this.isAllSelect = this.$parent.todos.every(todo=>todo.complate === true);
                if (this.isAllSelect) {
                    this.$parent.todos.forEach(todo=>{
                        todo.complate = false
                    });
                    this.isAllSelect = false
                } else {
                    this.$parent.todos.forEach(todo=>{
                        todo.complate = true
                    });
                    this.isAllSelect = true
                }

            },

            deleteComplated () {
                this.$parent.todos =  this.$parent.todos.filter(todo => {
                    return todo.complate === false
                })
            }
        },
        computed : {
            complated () {
                return this.$parent.todos.reduce((total, todo) => {
                    return total + todo.complate
                }, 0)
            }
        }
    }
</script>

<style scoped  lang="less">
    .bottom{
        width: 100%;
        height: 50px;
        /*margin-top: 20px;*/
        display: flex;
        align-items: center;
        justify-content: space-between;
        .selectAll{
            margin-left: 10px;
        }
        .complate{}
        button{
            background-color: red;
            color: white;
            margin-right: 20px;
            outline: none;
            border: 1px solid red;
        }

    }
</style>

3. 效果图

vue 组件化综合案例demo

相关标签: Vue