一、使用的工具
二、项目结构
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/45e53b83ba27b71baa9ffe31f5ed4ab6.png)
三、使用步骤
1. 初始化项目
- 在终端定位到需要创建项目的目录输入
npm init vite-app todoList
npm install less -D
安装less- 导入bootstrap
2.项目源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
<template>
<div>
<h1>App根组件</h1>
<hr />
<todoInput @add="taskActive"></todoInput>
<todoList :taskList="taskList"></todoList>
<todoButton v-model:active="activeBtnIndex"></todoButton>
</div>
</template>
<script>
import todoList from './components/to-do-list/todoList.vue'
import todoInput from './components/to-do-input/todoInput.vue'
import todoButton from './components/to-do-button/todoButton.vue'
export default {
name: 'App',
data() {
return {
list: [
{ id: 1, listName: '吃饭', state: false },
{ id: 2, listName: '睡觉', state: false },
{ id: 3, listName: '打游戏', state: false }
],
taskId: 4,
activeBtnIndex: 0
}
},
methods: {
taskActive(taskContent) {
this.list.push({
id: this.taskId,
listName: taskContent,
state: false
})
this.taskId++
}
},
computed: {
taskList() {
switch (this.activeBtnIndex) {
case 0:
return this.list
case 1:
return this.list.filter(x => x.state)
case 2:
return this.list.filter(x => !x.state)
}
}
},
components: {
todoList,
todoInput,
todoButton
}
}
</script>
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import './assets/css/bootstrap.min.css'
createApp(App).mount('#app')
#app {
margin-top: 10px;
}
<template>
<div class="button-container mt-3">
<div class="btn-group">
<button type="button" class="btn" :class="active === 0 ? 'btn-primary' : 'btn-secondary'" @click="onBtnClick(0)">全部</button>
<button type="button" class="btn" :class="active === 1 ? 'btn-primary' : 'btn-secondary'" @click="onBtnClick(1)">已完成</button>
<button type="button" class="btn" :class="active === 2 ? 'btn-primary' : 'btn-secondary'" @click="onBtnClick(2)">未完成</button>
</div>
</div>
</template>
<script>
export default {
name: 'todoButton',
props: {
active: {
type: Number,
required: true,
defalut: 0
}
},
emits: ['update:active'],
methods: {
onBtnClick(index) {
if (index === this.active) return
this.$emit('update:active', index)
}
}
}
</script>
<style lang="less" scoped>
.button-container {
width: 400px;
text-align: center;
}
</style>
<template>
<div>
<form @submit.prevent="addTask">
<div class="form-row align-items-center">
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">任务</div>
</div>
<input type="text" class="form-control" id="inlineFormInputGroup" placeholder="输入你将要完成的任务" v-model.trim="taskContent" />
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2">提交</button>
</div>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'todoInput',
data() {
return { taskContent: '' }
},
emits: ['add'],
methods: {
addTask() {
if (!this.taskContent) return alert('输入的内容不能为空!')
this.$emit('add', this.taskContent)
this.taskContent = ''
}
}
}
</script>
<style lang="less" scoped></style>
<template>
<div>
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center" v-for="item in taskList" :key="item.id">
<input type="checkbox" :id="item.id" v-model="item.state" />
<label :for="item.id" :class="item.state ? 'del' : ''">{{ item.listName }}</label>
<span class="badge badge-success badge-pill" v-if="item.state">已完成</span>
<span class="badge badge-warning badge-pill" v-else>未完成</span>
</li>
</ul>
</div>
</template>
<script>
export default {
props: ['taskList'],
name: 'todoList'
}
</script>
<style lang="less" scoped>
li {
width: 400px;
}
.del {
text-decoration: line-through;
font-style: italic;
color: gray;
}
</style>
四、项目效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/06d1bd357f23874169bab996517e9690.png)
五、项目地址
todoList