Distributor deep TodoList component design

<! -- src/components/TodoList/Index.vue --> <template> <div> <td-title :title="title" /> <td-form @dispatch="dispatch" /> <td-list :todoData="todoData" @dispatch="dispatch" /> </div> </template> <script> import TdTitle from "./Title"; import TdForm from "./Form"; import TdList from "./List/Index"; import dispatch from "@/dispatchers/todoList" export default { name: "TodoList", components: { TdTitle, TdForm, TdList }, data () { return { title: "TodoList", todoData: [] } }, methods: { dispatch (... args) { dispatch(this)(... args); } } } </script>Copy the code
<! -- src/components/TodoList/Title.vue --> <template> <h1>{{title}}</h1> </template> <script> export default { name: "TdTitle", props: { title: String } } </script>Copy the code
<! -- src/components/TodoList/Form.vue --> <template> <div> <form @submit="submitText"> <input type="text" v-model.trim="todoText" placeholder="Input what you wanna add!" /> </form> </div> </template> <script> export default { name: "TdForm", data () { return { todoText: "" } }, methods: { submitText (e) { e.preventDefault(); if (this.todoText.length === 0) { return; } this.$emit("dispatch", "ADD", { id: Date.now(), text: this.todoText, completed: false }); this.todoText = ""; } } } </script>Copy the code
<! -- src/components/TodoList/List/Index.vue --> <template> <div> <ul> <list-item v-for="(item, index) of todoData" :key="index" :item="item" @handelItem="handelItem" /> </ul> </div> </template> <script> import ListItem from './ListItem.vue' export default { name: "TdList", components: { ListItem }, props: { todoData: Array }, methods: { handelItem (... args) { this.$emit("dispatch", ... args); } } } </script>Copy the code
<! -- src/components/TodoList/List/ListItem.vue --> <template> <li> <input type="checkbox" :checked="item.completed ? 'checked' : '' " @click="handelItem('COMPLETED', item.id)" /> <span :class="{completed: item.completed}">{{item.text}}</span> <button @click="handelItem('REMOVE', </button> </li> </template> <script> export default {name: "ListItem", props: {item: Object}, methods: { handelItem (... args) { this.$emit("handelItem", ... args); } } } </script> <style scoped> .completed { text-decoration: line-through; } </style>Copy the code
<! -- src/actions/todoList.js --> const ADD = "ADD"; const REMOVE = "REMOVE"; const COMPLETED = "COMPLETED"; export { ADD, REMOVE, COMPLETED }Copy the code
<! -- src/reducers/todoList.js --> function todoListReducers (data) { function addItem (newItem) { return data.concat(newItem); } function removeItem (id) { return data.filter(item => item.id ! == id); } function changeCompleted (id) { return data.map((item) => { if (item.id === id) { item.completed = ! item.completed; } return item; }) } return { addItem, removeItem, changeCompleted } } export default todoListReducers;Copy the code
    <!-- src/dispatchers/todoList.js -->
    import todoListReducers from "../reducers/todoList";
    import { ADD, REMOVE, COMPLETED } from "@/actions/todoList";

    export default (ctx) => {
        const {
            addItem,
            removeItem,
            changeCompleted
        } = todoListReducers(ctx.todoData);

        return function (type, args) {
            console.log(type, args)
            switch (type) {
                case ADD:
                    ctx.todoData = addItem(args);
                    break;
                case REMOVE:
                    ctx.todoData = removeItem(args);
                    break;
                case COMPLETED:
                    ctx.todoData = changeCompleted(args);
                    break;
                default: 
                    break;
            }
        }
    }
Copy the code