【尚硅谷vue】p80 组件自定义事件: 子组件 传参 给父组件

p80 组件自定义事件: 子组件 传参 给父组件

子组件传参给父组件有个前提,就是“得提前给 一个函数”, 在合适的时候调用那个函数。

(笔记都写在了代码注释中)


App.vue

<template>
	<div class="app">
		<h1>{{ msg }},学生姓名是:{{ studentName }}</h1>

		<!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
		<!-- 还可以绑定【函数】,函数名 和 变量名都是地址指针 -->
		<School :getSchoolName="getSchoolName" />

		<!-- 1、通过父组件给子组件绑定一个自定义事件实现:
			【子给父传递数据】(第一种写法,使用@或v-on) 
			子组件中通过 $emit 触发事件,(父传子 只需要子组件中 props接收就好了)
			【父组件中绑定,子组件中触发】
			2、模板里写什么都不需要this
		-->
		<!-- <Student @atguigu="getStudentName" /> -->
		<!-- <Student @atguigu.once="getStudentName" /> -->
		<!-- <Student @atguigu="getStudentName" @demo="m1" /> -->

		<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
		<!-- <Student ref="student"/> -->

		<!--  @click="show" 会被认为是自定义事件, @click.native才会被认为原生DOM事件-->
		<!-- Student中不让写两个根元素(最外层的div) @click.native事件就把对象给到最外层的根元素了-->
		<Student ref="student" @click.native="show" />
	</div>
</template>

<script>
import Student from './components/Student'
import School from './components/School'

export default {
	name: 'App',
	components: { School, Student },
	data() {
		return {
			msg: '你好啊!',
			studentName: ''
		}
	},
	methods: {
		getSchoolName(name) {
			// 因为 函数名传递给了子组件,所以子组件中能够访问该函数(函数具有传参的功能)
			console.log('App收到了学校名:', name)

		},
		// 只要是methods里面的this,就一定指向App的vc
		getStudentName(name, ...params) {   // 接收后面的内容
			console.log('App收到了学生名:', name, params)
			this.studentName = name
		},
		m1() {
			console.log('demo事件被触发了!')
		},
		show() {
			alert(123)
		}
	},

	// APP只要挂载完毕,就【自动加载】
	// 之所以需要【挂载】是因为没有事件触发,所以需要挂载
	mounted() {
		// $on :【监听】当……时候,当atguigu事件被 (子组件)【触发$emit】的时候,(父组件)执行【回调】 this.getStudentName
		// this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(监听一次)

		// 1-1、这里调用了一次函数:(推荐第一种写法)
		// this是指向Student的vc,但是调用的函数里面的this以App的vc为主!
		this.$refs.student.$on('atguigu', this.getStudentName) //绑定自定义事件,此方法更加灵活,可以等ajax发回来一个请求后再执行

		// 1-2、要是写成以下:有坑 this指向问题
		/* this.$refs.student.$on('atguigu', function(name, ...params){
			console.log('App收到了学生名:', name, params)
			console.log(this);  //this:Student 的 VueComponent组件,不是App的,因为是Student组件触发的
		// 	this.studentName = name  // 不起作用
		}) */

		// 1-3、箭头函数:箭头函数没有自己的this,就往外找,找到mounted的this ,即App的vc
		/* this.$refs.student.$on('atguigu', (name, ...params) => {
			console.log('App收到了学生名:', name, params)
			console.log(this);  //this:Student 的 VueComponent组件,不是App的,因为是Student组件触发的
			this.studentName = name  //正确 
		}) */
	},

	/* mounted() {
		setTimeout(()=>{
			this.$refs.student.$on('atguigu', this.getStudentName)
		}, 3000)
		// 子组件中就算【触发】了事件,也得等到3s才反应。
	}, */
}
</script>

<style scoped>
.app {
	background-color: gray;
	padding: 5px;
}
</style>

-{{name}} 的来源:data、props、computed 计算属性

在这里插入图片描述


main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
	el: '#app',
	render: h => h(App),
	/* mounted() {
		setTimeout(() => {
			this.$destroy()
		}, 3000)
	}, */
})

components/School.vue

<template>
	<div class="school">
		<h2>学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
		<button @click="sendSchoolName">把学校名给App</button>
	</div>
</template>

<script>
	export default {
		name:'School',
		// 接收父组件传下来的,把getSchoolName函数放在 VueComponent(this) 上
		props:['getSchoolName'],
		data() {
			return {
				name:'尚硅谷',
				address:'北京',
			}
		},
		methods: {
			sendSchoolName(){
				console.log(this);  //VueComponent 
				// 把子组件的参数 通过函数传递上父组件
				//这里的this.getSchoolName,和父组件getSchoolName 都指向同一个 函数地址,父组件和子组件都可以调用这个函数
				this.getSchoolName(this.name)
			}
		},
	}
</script>

<style scoped>
	.school{
		background-color: skyblue;
		padding: 5px;
	}
</style>

components/Student.vue

<template>
	<div class="student">
		<h2>学生姓名:{{ name }}</h2>
		<h2>学生性别:{{ sex }}</h2>
		<h2>当前求和为:{{ number }}</h2>
		<button @click="add">点我number++</button>
		<button @click="sendStudentlName">把学生名给App</button>
		<button @click="unbind">解绑atguigu事件</button>
		<button @click="death">销毁当前Student组件的实例(vc)</button>
	</div>
</template>

<script>
export default {
	name: 'Student',
	data() {
		return {
			name: '张三',
			sex: '男',
			number: 0
		}
	},
	methods: {
		add() {
			console.log('add回调被调用了')
			this.number++
		},
		sendStudentlName() {
			//【触发】Student组件实例身上的atguigu事件,即 @atguigu = xxx事件
			this.$emit('atguigu', this.name, 666, 888, 900)
			// this.$emit('demo')
			// this.$emit('click')
		},
		unbind() {
			this.$off('atguigu') //解绑一个自定义事件
			// this.$off(['atguigu','demo']) //解绑多个自定义事件
			// this.$off() //解绑所有的自定义事件
		},
		death() {
			this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不能用了,但是原生的js可以使用
		}
	},
}
</script>

<style lang="less" scoped>
.student {
	background-color: pink;
	padding: 5px;
	margin-top: 30px;
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值