VUE使用props实现父给子组件传参,子给父组件传参,实现待办事项小案例

效果图

todolist
这里是参考的b站上面尚硅谷张天禹老师的课程
https://www.bilibili.com/video/BV1Zy4y1K7SH/?vd_source=1b08984208faca5ecf70d67f06a3962a
如有侵权还请速速联系

App.vue

这里用到的是父组件给子组件传参 :todos = “todos”,todos是值的名字,引号里面的是要传递的值

注意:这里不仅可以传递数据,还可以传递方法 :checkAllTodo=“checkAllTodo”

这里用到了filter() 过滤 留下满足条件的内容,该方法不会改变原数组,所以需要重新赋值

<template>
	<div class="content">
		<MyHeader :addTodo="addTodo"></MyHeader>
		<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo" ></MyList>
		<MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"></MyFooter>
	</div>
</template>

<script>
	import MyHeader from './components/MyHeader.vue'
	import MyFooter from './components/MyFooter.vue'
	import MyList from './components/MyList.vue'
	export default {
		name: 'App',
		components: {
			MyHeader,
			MyFooter,
			MyList
		},
		data() {
			return {
				todos: [{
						id: '001',
						title: '打代码',
						done: false
					},
					{
						id: '002',
						title: '睡觉',
						done: true
					},
					{
						id: '003',
						title: '吃饭',
						done: false
					}
				]
			}
		},

		methods: {
			// 数据在哪里,数据操作的方法就在那里
			// 添加todo
			addTodo(todoObj) {
				// console.log('我是app组件我收到了数据',todoObj)
				this.todos.unshift(todoObj)
			},
			// 勾选or取消一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id){
						todo.done = !todo.done
					}
				})
			},
			// 删除todo
			deleteTodo(id){
				// filter不会改变原数组 ,留下满足条件的
				this.todos = this.todos.filter((todo)=>{
					return todo.id !== id
				})
			},
			// 全选
			checkAllTodo(done){
				this.todos.forEach((todo)=>{
					todo.done = done
				})
				
			},
			// 删除已完成
			clearAllTodo(){
				this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})
			}
		}
	}
</script>

<style>
	.content {
		width: 600px;
		border: 1px solid #ddd;
		padding: 10px;
		margin: 0 auto;
		border-radius: 10px;
	}
</style>

组件MyHeader

这里主要是来实现添加功能的 add()

注意:这里便是子组件给父组件传参,通过props的话需要父组件提前声明函数并传递子组件 addTodo(),然后子组件接收,调用即可

这里用到了trim()方法,去除字符串前后的空格,这个方法在表单校验时很常用
还用到了uuid可以生成全球唯一的字符串,可以考虑做测试的时候用 nanoid是这个的精简版

<template>
	<div class="headerContent">
		<input type="text" placeholder="请输入您的任务名称,按回车确认" v-model="title" @keydown.enter="add">
	</div>
</template>

<script>
	// 分别暴露
	import {nanoid} from 'nanoid'
	export default {
		name: 'MyHeader',
		data() {
			return {
				title: ''
			}
		},
		props:['addTodo'],
		methods: {
			add(){
				// console.log(e.target.value)
				// console.log(this.title)
				
				// 将用户的输入包装成一个todo对象
				// uuid生成唯一字符串编码,比较大  变种nanoid - 精简版
				// 校验数据
				// trim()去掉空格
				if(this.title.trim()){
					const todoObj = {id:nanoid(),title:this.title,done:false}
					// 通知app组件去添加一个对象
					this.addTodo(todoObj)
					// 清空内容
					this.title = ""
				}else{
					alert('输入内容不能为空')
					return
				}
				
			}
		}
	}
</script>

<style scoped>
	.headerContent {
		width: 100%;
		border: 1px solid #ddd;
		padding: 5px 10px;
		box-sizing: border-box;
	}

	.headerContent input {
		width: 100%;
		height: 30px;
		box-sizing: border-box;
		outline: none;
		border: none;
	}
</style>

组件MyList

这里实现的功能主要有,内容的遍历与显示,以及数据的传递。

注意:如果使用props只能逐层传递,App-----MyList----MyItem
<template>
	<div class="listContent">
		<MyItem v-for="todoObj in todos" :key="todoObj.id" :todo = "todoObj" :checkTodo="checkTodo" :deleteTodo="deleteTodo"></MyItem>
	</div>
</template>

<script>
	import MyItem from '../components/MyItem'
	export default {
		name: 'MyList',
		components: {
			MyItem
		},
		
		props: ['todos','checkTodo','deleteTodo'],
		methods:{
			
		}
	}
</script>

<style scoped>

</style>

组件MyItem

这里实现的功能主要为每一项的勾选,以及每一项删除功能
这里用到了confirm()点击确定之后才会执行下面的内容,否则跳出

<template>
	<div class="itemContent">
		<div>
			<input type="checkbox" :checked = "todo.done" @click="handleCheck(todo.id)" /> {{todo.title}}
		</div>
		<div class="delBtn" @click="handleDelete(todo.id)">删除</div>
	</div>
</template>

<script>
	export default {
		name: 'MyItem',
		// 声明接收todo对象
		props:['todo','checkTodo','deleteTodo'],
		methods:{
			// 勾选活取消
			handleCheck(id){
				// 通知app调用勾选
				this.checkTodo(id)
			},
			// 删除
			handleDelete(id){
				// confirm 确定为真,取消为假
				if(confirm('确定删除吗??')){
					// 通知app删除对应项
					this.deleteTodo(id)
				}
			}
		},
	}
</script>

<style scoped>
	.itemContent {
		border: 1px solid #ddd;
		margin-top: 5px;
		width: 100%;
		height: 40px;
		padding: 5px 10px;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		justify-content: space-between;
		transition: .3s;
	}
	.delBtn{
		padding: 5px 10px;
		background: #f40;
		color: #fff;
		border-radius: 5px;
		display: none;
		transition: .3s;
		cursor: pointer;
	}
	.itemContent:hover{
		background-color: #ddd;
	}
	.itemContent:hover .delBtn{
		display: block;
	}
</style>

组件MyFooter

这里实现的主要是,事项的统计,以及删除已完成,实现全选或全不选功能
两个计算属性是可以同时使用的
这里还用到了reduce

<template>
	<div class="footerContent" v-show="total">
		<div>
			<!-- <input type="checkbox" :checked="isAll" @change="checkAll"> -->
			<input type="checkbox" v-model="isAll">
			已完成{{doneTotal}} / 全部{{total}}
		</div>
		<div class="delAll" @click="clearAll">
			清除已完成任务
		</div>
	</div>
</template>

<script>
	export default {
		name: 'MyFooter',
		props:['todos','checkAllTodo','clearAllTodo'],
		computed:{
			total(){
				return this.todos.length
			},
			doneTotal(){
				// let i = 0 
				// this.todos.forEach((todo)=>{
				// 	if(todo.done){
				// 		i++
				// 	}
				// })
				// return i
				// es6 reduce专门做条件统计的 第一个参数为上一次返回值,第二个参数为每一个项
				// 该函数数的最终返回值为pre的最后值
				return this.todos.reduce((pre,todo)=>{
					return pre + (todo.done ? 1 : 0)
				},0)
				
			},
			isAll:{
				get(){
					return this.doneTotal === this.total && this.total > 0
				},
				set(value){
					this.checkAllTodo(value)
				}
			}
		},
		methods:{
			// checkAll(e){
			// 	this.checkAllTodo(e.target.checked)
			// }
			clearAll(){
				this.clearAllTodo()
			}
		}
	}
</script>

<style scoped>
	.footerContent {
		width: 100%;
		height: 40px;
		margin-top: 5px;
		display: flex;
		align-items: center;
		padding: 5px 10px;
		box-sizing: border-box;
		justify-content: space-between;
	}
	.delAll{
		padding: 5px 10px;
		background: #f40;
		color: #fff;
		border-radius: 5px;
		cursor: pointer;
	}
</style>

每天记录一个小案例!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值