一个vue3的待办列表组件

一个vue3的待办列表组件, 仿企业微信的待办列表

TodoList.vue

js 复制代码
<template>
    <div>
        <el-input v-model="todoInput" placeholder="写下你的待办事项..." class="el-input" @keyup.enter="addTodo"
            input-style="background-color: #EBECED;" />

        <el-table :data="todos" size="small" :show-header="false" @row-dblclick="editTodo">
            <el-table-column width="30">
                <template #default="scope">
                    <el-checkbox v-model="scope.row.completed" @change="toggleTodo(scope.row)">check</el-checkbox>
                </template>
            </el-table-column>
            <el-table-column prop="text" />
        </el-table>

        <div @click="showCompleted = !showCompleted" style="cursor: pointer; text-align: center; margin: 10px 0;">
            <el-divider v-if="!showCompleted">已完成 (点击展开)</el-divider>
            <el-divider v-else>已完成 (点击折叠)</el-divider>
        </div>

        <el-table :data="completedTodos" size="small" :show-header="false" v-if="showCompleted">
            <el-table-column width="30">
                <template #default="scope">
                    <el-checkbox v-model="scope.row.completed" @change="toggleTodo(scope.row)">check</el-checkbox>
                </template>
            </el-table-column>
            <el-table-column prop="text" />
        </el-table>

        <el-dialog title="修改" v-model="editDialogVisible">
            <el-form :model="editingTodo">
                <el-form-item label="内容">
                    <el-input ref="inputRef" v-model="editingTodo.text"></el-input>
                </el-form-item>
                <el-form-item label="状态">
                    <el-checkbox v-model="editingTodo.completed">已完成</el-checkbox>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="editDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="confirmEdit()">确 定</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
// 通用的待办列表
// 使用<TodoList :todoList="todoList" :save="save"></TodoList>
import { ref } from 'vue';

interface Todo {
    id: number;
    text: string;
    completed: boolean;
}

defineOptions({
    name: 'TodoList'
})

const props = defineProps({
    todoList: Array<Todo>,
    save: Function  //外部传入的保存方法,入参是Todo[]
});

const todoInput = ref('');
const todos = ref<Todo[]>([]);
const completedTodos = ref<Todo[]>([]);
const editDialogVisible = ref(false);
const editingTodo = ref({} as Todo);
const showCompleted = ref(false);
const inputRef = ref();

watch(() => props.todoList, (newValue) => {
    if (newValue) {
        newValue.sort((a, b) => b.id - a.id);
        todos.value = newValue.filter(t => !t.completed);
        completedTodos.value = newValue.filter(t => t.completed);
    }
})

const addTodo = () => {
    if (todoInput.value.trim() === '') return;
    todos.value.unshift({
        id: Date.now(),
        text: todoInput.value,
        completed: false
    });
    todoInput.value = '';
    saveTodoList();
};

const toggleTodo = async (todo: Todo) => {
    await new Promise(resolve => setTimeout(() => resolve("delay"), 300)); //产生一个点击后动画效果
    if (todo.completed) {
        if (!completedTodos.value.find(t => t.id == todo.id)) {
            completedTodos.value.unshift(todo);
        }
        todos.value = todos.value.filter(t => t.id !== todo.id);
    } else {
        if (!todos.value.find(t => t.id == todo.id)) {
            todo.id = Date.now();//更新时间到最新,所以每个todo其实是没有唯一值的
            todos.value.unshift(todo);
        }
        completedTodos.value = completedTodos.value.filter(t => t.id !== todo.id);
    }
    saveTodoList();
};

const editTodo = (todo: Todo) => {
    editingTodo.value = { ...todo };
    editDialogVisible.value = true;
    //组件focus的正确方式 setTimeout
    setTimeout(() => {
        inputRef.value?.focus();
    })
};

const confirmEdit = () => {
    editDialogVisible.value = false;
    var todo = todos.value.find(t => t.id == editingTodo.value.id)
    if (todo) {
        todo.text = editingTodo.value.text
        todo.completed = editingTodo.value.completed;
        toggleTodo(todo);
    }
};

const saveTodoList = () => {
    if (props.save) { // 添加空值检查
        props.save(todos.value.concat(completedTodos.value));
    }
}

</script>
<style scoped>
.el-input {
    --el-input-bg-color: #EBECED;
}
</style>
相关推荐
fangzhanpeng16815 小时前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心3 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u0103055279 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u0103055279 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝11 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552711 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552711 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552714 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552714 天前
Java I/O核心操作实战
人工智能·1024程序员节
u01030552715 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节