一个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>
相关推荐
yaosheng_VALVE15 小时前
探究全金属硬密封蝶阀的奥秘-耀圣控制
运维·eclipse·自动化·pyqt·1024程序员节
dami_king16 小时前
SSH特性|组成|SSH是什么?
运维·ssh·1024程序员节
一个通信老学姐5 天前
专业125+总分400+南京理工大学818考研经验南理工电子信息与通信工程,真题,大纲,参考书。
考研·信息与通信·信号处理·1024程序员节
sheng12345678rui5 天前
mfc140.dll文件缺失的修复方法分享,全面分析mfc140.dll的几种解决方法
游戏·电脑·dll文件·dll修复工具·1024程序员节
huipeng9266 天前
第十章 类和对象(二)
java·开发语言·学习·1024程序员节
earthzhang20217 天前
《深入浅出HTTPS》读书笔记(19):密钥
开发语言·网络协议·算法·https·1024程序员节
爱吃生蚝的于勒8 天前
计算机基础 原码反码补码问题
经验分享·笔记·计算机网络·其他·1024程序员节
earthzhang20218 天前
《深入浅出HTTPS》读书笔记(20):口令和PEB算法
开发语言·网络协议·算法·https·1024程序员节
一个通信老学姐8 天前
专业140+总分410+浙江大学842信号系统与数字电路考研经验浙大电子信息与通信工程,真题,大纲,参考书。
考研·信息与通信·信号处理·1024程序员节
earthzhang20218 天前
《深入浅出HTTPS》读书笔记(18):公开密钥算法RSA(续)
网络·网络协议·算法·https·1024程序员节