用Vue3实现的一个TodoLists案例

这是一个用Vue3实现的一个TodoList案例。

下面这张图是最终的实现效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SeBhHpW-1658062507643)(attachment:8a0a35a2984202df0633d789960dcbb9)]

下面是代码实现

一、项目骨架

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h2>{{title}}</h2>
        <input type="text" v-model="title">
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        const App = {
            data() {
                return {
                    title: "",
                }
            },
        }

        Vue.createApp(App).mount('#app');
    </script>
</body>
</html>

二、任务列表

<div id="app">
    <h2>{{title}}</h2>
    <input type="text" v-model="title">
    <ul>
        <li v-for="todo in todos">{{todo}}</li>
    </ul>
</div>
const App = {
    data() {
        return {
            title: "",
            todos: ['吃饭', '睡觉']
        }
    },
}

三、添加操作

const App = {
    data() {
        return {
            title: "",
            todos: ['吃饭', '睡觉']
        }
    },
    methods: {
        addTodo() {
            this.todos.push(this.title);
            this.title = "";
        }
    },
}

四、数组内改为对象

<div id="app">
    <h2>{{title}}</h2>
    <input type="text" v-model="title" @keydown.enter="addTodo">
    <ul>
        <li v-for="todo in todos">
            <input type="checkbox" v-model="todo.done">
            <span>{{todo.title}}</span>
        </li>
    </ul>
</div>
const App = {
    data() {
        return {
            title: "",
            todos: [
                {title: '吃饭', done: false},
                {title: '睡觉', done: false},
            ]
        }
    },
    methods: {
        addTodo() {
            this.todos.push({
                title: this.title,
                done: false
            });
            this.title = "";
        }
    },
}

五、底部全选实现

<div id="app">
    <h2>{{title}}</h2>
    <input type="text" v-model="title" @keydown.enter="addTodo">
    <ul>
        <li v-for="todo in todos">
            <input type="checkbox" v-model="todo.done">
            <span>{{todo.title}}</span>
        </li>
    </ul>
    <div>
        全选
        <input type="checkbox" v-model="allDone">
        <span>{{active}} / {{all}}</span>
    </div>
</div>
computed: {
    active() {
        return this.todos.filter(todo => !todo.done).length
    },
    all() {
        return this.todos.length
    },
    allDone: {
        get() {
            return this.active === 0
        },
        set(val) {
            this.todos.forEach(todo => todo.done = val)
        }
    }
},

六、清除已完成任务

<button @click="clear" v-if="active<all">清理</button>
clear() {
    this.todos = this.todos.filter(todo => !todo.done)
}

七、完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .done {
            color: grey;
            text-decoration: line-through;
        }
    </style>
</head>
<body>
    <div id="app">
        <h2>{{title}}</h2>
        <input type="text" v-model="title" @keydown.enter="addTodo">
        <button @click="clear" v-if="active<all">清理</button>
        <ul>
            <li v-for="todo in todos">
                <input type="checkbox" v-model="todo.done">
                <span :class="{done: todo.done}">{{todo.title}}</span>
            </li>
        </ul>
        <div>
            全选
            <input type="checkbox" v-model="allDone">
            <span>{{active}} / {{all}}</span>
        </div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        const App = {
            data() {
                return {
                    title: "",
                    todos: [
                        {title: '吃饭', done: false},
                        {title: '睡觉', done: false},
                    ]
                }
            },
            methods: {
                addTodo() {
                    this.todos.push({
                        title: this.title,
                        done: false
                    });
                    this.title = "";
                },
                clear() {
                    this.todos = this.todos.filter(todo => !todo.done)
                }
            },
            computed: {
                active() {
                    return this.todos.filter(todo => !todo.done).length
                },
                all() {
                    return this.todos.length
                },
                allDone: {
                    get() {
                        return this.active === 0
                    },
                    set(val) {
                        this.todos.forEach(todo => todo.done = val)
                    }
                }
            },
            watch: {
                todos: {
                    handler(newVal, oldVal) {
                        console.info("todos->change")
                        localStorage.setItem("todos", JSON.stringify(this.todos))
                    },
                    deep: true
                }
            },
            mounted() {
                //加载数据
                var todos = localStorage.getItem("todos");
                if (todos) {
                    this.todos = JSON.parse(todos);
                }
            },
            unmounted() {
                //保存数据
                localStorage.setItem("todos", JSON.stringify(this.todos))
            },
        }

        Vue.createApp(App).mount('#app');
    </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值