0.最终样式演示
完整代码地址
GitHub:https://github.com/xiaoxin179/tasklist
概述:目的在于熟悉vue的各种语法,做出一点小成品,话费少量的事件,提升学习兴趣
1.构建vue工程
使用vite+boostrap
//命令行创建vite项目
npm init vite-app tasklist
npm install
npm run dev
2.代码细节
0.app.vue
<template>
<div class="app">
<h1>任务清单</h1>
<AddTask @addTask="addTask"/>
<!-- 字符组件之间的传值 -->
<TaskList :tasklist="tasklist"></TaskList>
<TodoButton @changeActive="changeActive"/>
</div>
</template>
<script>
import TaskList from './components/TaskList.vue'
import TodoButton from './components/TodoButton.vue'
import AddTask from './components/AddTask.vue'
export default {
name: "App",
data(){
return{
active:0,
tasklist:[
{id:1,task:'吃饭',isCompleted:true},
{id:2,task:'洗衣服',isCompleted:true},
{id:3,task:'玩手机',isCompleted:false}
]
}
},
// 计算属性,响应式式数据计算之后返回新的值,就是计算之后让todolist为新的值,通过这个来实现过滤的效果
computed:{
tasklist(){
if(this.active === 0){
return this.tasklist
}else if(this.active === 1){
return this.tasklist.filter(item =>item.isCompleted)
}else{
return this.tasklist.filter(item =>!item.isCompleted)
}
}
},
components: {
TaskList,
TodoButton,
AddTask
},
methods:{
changeActive(active){
this.active=active
// 测试值是否传递过来
// console.log(this.active);
},
addTask(taskname){
this.tasklist.push({
id:this.tasklist.length+1,
task:taskname,
isCompleted:false
})
}
},
};
</script>
A.TaskList.vue --任务列表
<template>
<div>
<div class="list">
<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"
>
<!-- 复选框 -->
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value=""
:id="item.id"
v-model="item.isCompleted"
/>
<!-- 动态绑定css属性 -->
<label class="form-check-label" :for="item.id" :class="item.isCompleted?'del':''">
{{item.task}}
</label>
</div>
<span class="badge badge-primary badge-pill" v-if="item.isCompleted">已完成</span>
<span class="badge badge-warning badge-pill" v-else>未完成</span>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
tasklist: {
type: Array,
required: true
}
},
data() {
return {
name: "TaskList",
};
},
};
</script>
<style scoped>
.list-group {
width: 500px;
margin: 20px auto;
}
.del{
text-decoration: line-through;
}
</style>
代码解释:
子父数据传递
在父组件app.vue中,定义数据具有的属性
tasklist:[
{id:1,task:'吃饭',isCompleted:true},
{id:2,task:'洗衣服',isCompleted:true},
{id:3,task:'玩手机',isCompleted:false}
]
在子组件中接受
props: {
// 定义require的值为true的意思就是父组件必须给子组件传递这个参数
tasklist: {
type: Array,
required: true
}
},
完成的任务css动态属性绑定
<label class="form-check-label" :for="item.id" :class="item.isCompleted?'del':''">
//在css中定义del
.del{
text-decoration: line-through;
}
完成未完成的标签显示
<span class="badge badge-primary badge-pill" v-if="item.isCompleted">已完成</span>
<span class="badge badge-warning badge-pill" v-else>未完成</span>
B.TodoButton.vue
<template>
<div class="taskbutton">
<div class="btn-group" role="group" aria-label="Basic example">
<button
type="button"
class="btn"
:class="active === 0 ? 'btn-primary' : 'btn-secondary'"
@click="changeActive(0)"
>
全部计划
</button>
<button
type="button"
class="btn"
:class="active === 1 ? 'btn-primary' : 'btn-secondary'"
@click="changeActive(1)"
>
完成计划
</button>
<button
type="button"
class="btn"
:class="active === 2 ? 'btn-primary' : 'btn-secondary'"
@click="changeActive(2)"
>
未完成计划
</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
namne: "TaskButton",
active: 0,
};
},
emit:["changeActive"],
methods:{
changeActive(index){
this.active=index;
// <!-- emit的作用是触发自定义事件,携带事件名,并且传递参数 -->
this.$emit('changeActive',index);
}
}
};
</script>
<style scoped>
.btn-group {
width: 500px;
}
</style>
代码解释
按钮被点击显示不同的颜色
思路:创建一个变量,然后csss属性动态绑定,如果变量的值0,代表第一个被点击到,为蓝色,点击事件就触发函数传递这个值,函数就是修改这个值
<button
type="button"
class="btn"
:class="active === 0 ? 'btn-primary' : 'btn-secondary'"
@click="changeActive(0)"
>
全部计划
</button>
父组件中表单数据的过滤
思路:通过emit来给父组件传递自定义事件,在父组件中通郭computed(计算)计算属性来过滤
//TodoList.vue
emit:["changeActive"],
methods:{
changeActive(index){
this.active=index;
// <!-- emit的作用是触发自定义事件,携带事件名,并且传递参数 -->
this.$emit('changeActive',index);
}
}
//app.vue
computed:{
tasklist(){
if(this.active === 0){
return this.tasklist
}else if(this.active === 1){
return this.tasklist.filter(item =>item.isCompleted)
}else{
return this.tasklist.filter(item =>!item.isCompleted)
}
}
},
C. AddTask.vue
代码:
<template>
<div class="add">
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="请输入需要添加的任务"
aria-label="Recipient's username"
aria-describedby="basic-addon2"
v-model="taskname"
/>
<button class="btn-primary" @click="submit">提交</button>
</div>
</div>
</template>
<script>
export default {
data() {
name: "addtask";
return {
taskname: "",
};
},
emits:["addTask"],
methods: {
submit() {
this.$emit('addTask',this.taskname)
this.taskname=""
},
},
};
</script>
<style scoped>
.add{
width: 500px;
margin: auto;
}
</style>
代码解释
给按钮输入的数据绑定,同时绑定按钮提交事件,vue的双向数据绑定所以也是需要在data中绑定数据
//AddTask.vue
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="请输入需要添加的任务"
aria-label="Recipient's username"
aria-describedby="basic-addon2"
v-model="taskname"
/>
<button class="btn-primary" @click="submit">提交</button>
</div>
通过emit创建自定义事件,同时,通过点击事件触发向父组件传递自定义事件和参数,然后在app.vue
中把他加到tasklist中
//AddTask.vue
emits:["addTask"],
methods: {
submit() {
this.$emit('addTask',this.taskname)
this.taskname=""
},
}
//app.vue
//组件名
<AddTask @addTask="addTask"/>
addTask(taskname){
this.tasklist.push({
id:this.tasklist.length+1,
task:taskname,
isCompleted:false
})
}