vue进阶篇 - 组件之间的数据传递

172 阅读2分钟

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」。


上一篇简单的和大家介绍了关于vue中插件的内容相信大家也受益匪浅,本期我会给大家介绍一下组件的使用方式,以后大家和组件这方面的内容将会不少打交道所以我在本期内容会和大家仔细的讲解一下关于这方面的内容。组件通过import的方式引用数据传递是在组件标签传递数据通过props获取向组件传递的数据;

如果下面图片中的<MyHeader />就是组件标签 :addTodo = “yyy”是数据其中addTodo是绑定的属性名称yyy则是表达式;

<template>
	<div id="root">
		<div class="todo-container">
			<div class="todo-wrap">
				<MyHeader :addTodo="addTodo"/>
				<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
				<MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
			</div>
		</div>
	</div>
</template>

<script>
	import MyHeader from './components/MyHeader'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter.vue'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				//由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
				todos:[
					{id:'001',title:'抽烟',done:true},
					{id:'002',title:'喝酒',done:false},
					{id:'003',title:'开车',done:true}
				]
			}
		},
		methods: {
			//添加一个todo
			addTodo(todoObj){
				this.todos.unshift(todoObj)
			},
			//勾选or取消勾选一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			},
			//全选or取消全选
			checkAllTodo(done){
				this.todos.forEach((todo)=>{
					todo.done = done
				})
			},
			//清除所有已经完成的todo
			clearAllTodo(){
				this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})
			}
		}
	}
</script>

可以将数据层层传递需要的只是可以通过v-bind的简写方式:xxx来传递数据。(如果不用v-bind就只是穿的字符串,用v-bind穿的是表达式)子传父数据可以在传子时通过v-bind来传函数,在子里面给函数传参来获取数据;

image.png

<template>
	<ul class="todo-main">
		<MyItem 
			v-for="todoObj in todos"
			:key="todoObj.id" 
			:todo="todoObj" 
			:checkTodo="checkTodo"
			:deleteTodo="deleteTodo"
		/>
	</ul>
</template>

<script>
	import MyItem from './MyItem'

	export default {
		name:'MyList',
		components:{MyItem},
		//声明接收App传递过来的数据,其中todos是自己用的,checkTodo和deleteTodo是给子组件MyItem用的
		props:['todos','checkTodo','deleteTodo']
	}
</script>

子组件给父组件传数据需要父组件给子组件传一个函数通过v-bind:的方式传因为v-bind:是可以穿表达式不是单独的字符串,传数据可以无限向下传递。

image.png

<template>
	<li>
		<label>
			<input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>
			<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
			<!-- <input type="checkbox" v-model="todo.done"/> -->
			<span>{{todo.title}}</span>
		</label>
		<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
	</li>
</template>

<script>
	export default {
		name:'MyItem',
		//声明接收todo、checkTodo、deleteTodo
		props:['todo','checkTodo','deleteTodo'],
		methods: {
			//勾选or取消勾选
			handleCheck(id){
				//通知App组件将对应的todo对象的done值取反
				this.checkTodo(id)
			},
			//删除
			handleDelete(id){
				if(confirm('确定删除吗?')){
					//通知App组件将对应的todo对象删除
					this.deleteTodo(id)
				}
			}
		},
	}
</script>

总结子组件给父组件传数据

  1. 组件化编码流程:

    ​ (1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。

    ​ (2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:

    ​ 1).一个组件在用:放在组件自身即可。

    ​ 2). 一些组件在用:放在他们共同的父组件上(状态提升)。

    ​ (3).实现交互:从绑定事件开始。

  2. props适用于:

    ​ (1).父组件 ==> 子组件 通信

    ​ (2).子组件 ==> 父组件 通信(要求父先给子一个函数)

  3. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

  4. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。