Vue框架总结(四、CLI编程组件通信)

一、 props配置项

props配置项:

  • 功能:让组件接收外部传过来的数据

  • 传递数据:<Student name="xxx"/>

  • 接收数据:

① 第一种方式(只接收):props:['name']

② 第二种方式(限制数据类型):props:{name:String}

③ 第三种方式(限制类型、限制必要性、指定默认值)

props:{
	name:{
		type:String, 	//类型
		required:true,  //必要性
		default:'划水艺术家'  //默认值
	}
}

测试案例:

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		<!--使用 props 传递数据-->
		<Student name="划水艺术家" age="20"></Student>
	</div>
</template>

src/components/Student.vue

<template>
	<div>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生年龄:{{age}}</h2>
	</div>
</template>

<script>
export default {
	name:'Student',
	
	// 简单声明接收
	// props:['name','age']
	
	// 接收的同时对数据进行类型限制
	/* props:{
			name:String,
			age:Number
	} */

	// 接收的同时对数据进行类型限制 + 指定默认值 + 限制必要性
	props: {
		name: {
			type: String,
			required: true,
		},
		age: {
			type: Number,
			default: 99
		}
	}
}
</script>

在这里插入图片描述

props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据


二、 父子组件通信

1. 父组件向子组件通信

子组件无法直接使用父组件中的数据,如果需要使用,则必须由父组件把数据传递给子组件才可以。
本质: 让子组件中的属性与父组件中的属性进行关联绑定, 然后子组件使用该属性, 这样才能做到数据传递。

测试案例:

在这里插入图片描述

src/components/Child.vue

<template>
	<div>
		<h1>子组件引用父组件数据</h1>
		<h2>姓名:{{name}}</h2>
		<h2>年龄:{{age}}</h2>
	</div>
</template>

<script>
export default {
	name: "Child",
	
	props:['name','age']

}
</script>

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		
		<!--向子组件通信-->
		<Child name="划水艺术家" age="20"></Child>
	
	</div>
</template>

<script>

import Child  from "./components/Child";

export default {
	name: 'App',
	components: {
		Child
	},
}

</script>

在这里插入图片描述


2. 子组件向父组件通信

****

① 基础方法

子组件无法直接给父组件传递数据,也无法操作父组件中的数据,更无法调用父组件中的方法。
所以,,所谓的子组件向父组件通讯,其实就是想办法让子组件调用父组件的方法,进而响应到父组件中的数据。

测试案例:

src/components/Child.vue

<template>
	<div>
		<h1>子组件向父组件通信</h1>
		<h2>姓名:{{name}}</h2>
		<h2>年龄:{{age}}</h2>
		<button @click="childFunc">点我年龄 + 1 并将姓名传送至父组件 App</button>
	</div>
</template>

<script>
export default {
	name: "Child",
	
	// 其中 func 为父组件向子组件传递的方法
	props:['name', 'age', 'func'],
	
	methods:{
		childFunc(){
			// 调用父组件传递的方法
			this.func(this.name);
		}
	}
}
</script>

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		
		<!--父组件给子组件传递必要参数以及函数便于子组件向父组件通信-->
		<Child name="划水艺术家" :age="age" :func="func"></Child>
		
	</div>
</template>

<script>


import Child  from "./components/Child";

export default {
	name: 'App',
	components: {
		Child
	},

	data() {
		return {
			age: 20
		}
	},
	
	methods:{
		func(name){
			this.age += 1
			console.log("子组件向父组件通信---name: ", name);
		}
	}
}

</script>

在这里插入图片描述


② 自定义事件

父组件可在子组件上绑定自定义事件,通过触发自定义事件,完成子组件向父组件通信。

组件的自定义事件:

  • 一种组件间通信的方式,适用于子组件向父组件通信

  • 绑定自定义事件:

方式①,在父组件中直接使用 v-on@ 绑定自定义事件:

<Child @my-event="func"/><Child v-on:my-event="func"/>

方式②,在父组件中引用子组件时使用 ref 属性,选取合适时机为子组件绑定事件:

<Child ref="child"/>
<script>
	...
	mounted(){
		this.$refs.child.$on('my-event', func)
	}
</script>
  • 可在自定义事件上添加事件修饰符

  • 触发自定义事件:this.$emit('my-event', 数据...)

  • 解绑自定义事件:

// 解绑一个自定义事件
// this.$off('my-event')

// 解绑多个自定义事件
// this.$off(['my-event'])

// 解绑所有自定义事件
this.$off()
  • 组件上也可以绑定原生DOM事件,需要使用native修饰符

  • 注意:通过this.$refs.xxx.$on('my-event', 回调函数)绑定自定义事件时,回调函数要么配置在methods中,要么用箭头函数,否则this指向会出问题!

测试案例:

src/components/Child.vue

<template>
	<div>
		<h1>子组件向父组件通信</h1>
		<h2>姓名:{{name}}</h2>
		<h2>年龄:{{age}}</h2>
		<button @click="childFunc">点我年龄 + 1 并将姓名传送至父组件 App</button>
	</div>
</template>

<script>
export default {
	name: "Child",
	
	props:['name', 'age'],
	
	methods:{
		childFunc(){
			// 触发 Child 组件实例身上的 my-event 事件
			this.$emit("my-event", this.name);
		}
	}
}
</script>

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		
		<!--父组件给子组件绑定自定义事件 (绑定事件使用 v-on 与 @ 均可)-->
		<Child name="划水艺术家" :age="age" v-on:my-event="func"></Child>
		
	</div>
</template>

<script>

import Child  from "./components/Child";

export default {
	name: 'App',
	components: {
		Child
	},

	data() {
		return {
			age: 20
		}
	},
	
	methods:{
		func(name){
			this.age += 1
			console.log("子组件向父组件通信---name: ", name);
		}
	}
}

</script>

在这里插入图片描述


③ 使用ref属性绑定自定义事件

在上述中绑定的自定义事件是当整个模板一被解析就直接绑定,当我们有些特别的需求,例如:在页面完成挂载5秒后才绑定事件,就需要使用ref属性。

测试案例:
与②中大致相同,只是绑定自定义事件的方式略有变化

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		
		<!--父组件给子组件绑定自定义事件 (使用 ref )-->
		<Child name="划水艺术家" :age="age" ref="child"></Child>

	</div>
</template>

<script>

import Child  from "./components/Child";

export default {
	name: 'App',
	components: {
		Child
	},

	data() {
		return {
			age: 20
		}
	},
	
	methods:{
		func(name){
			this.age += 1
			console.log("子组件向父组件通信---name: ", name);
		}
	},

	// 当页面挂载完毕5秒后给 child 组件绑定事件
	mounted(){
		setTimeout(()=>{
			this.$ref.child.$on("my-event", this.func);
		}, 5000);
	}
}

</script>

④ 自定义事件的解绑

给哪个组件绑定的事件,就在哪个组件中完成解绑。
在上述案例中,所定义的自定义事件my-event是给Child组件绑定的,因此若想要解绑,则在Child组件中完成。

src/components/Child.vue

<template>
	<div>
		<h1>子组件向父组件通信</h1>
		<h2>姓名:{{name}}</h2>
		<h2>年龄:{{age}}</h2>
		<button @click="childFunc">点我年龄 + 1 并将姓名传送至父组件 App</button>
		
		<button @click="unbind">解绑自定义事件</button> 
		
	</div>
</template>

<script>
export default {
	name: "Child",
	
	props:['name', 'age'],
	
	methods:{
		childFunc(){
			// 触发 Child 组件实例身上的 my-event 事件
			this.$emit("my-event", this.name);
		},
		unbind(){
			// 解绑一个自定义事件
			// this.$off('my-event')
			
			// 解绑多个自定义事件
			// this.$off(['my-event'])
			
			// 解绑所有自定义事件
			this.$off()
		}
	}
}
</script>

三、全局事件总线

全局事件总线(GlobalEventBus):

  • 一种组件间通信的方式,适用于任意组件间通信
  • 本质上就是一个对象。它必须满足以下条件:
    ① 所有的组件对象都必须能看见他
    ② 这个对象必须能够使用$on$emit$off方法去绑定、触发和解绑事件

使用步骤:

  • 安装全局事件总线:
new Vue({
	...
	beforeCreate() {
		//安装全局事件总线 
		Vue.prototype.$bus = this 
	},
	...
}) 
  • 使用事件总线:

① 接收数据:A组件想接收数据,则在A组件中给 $bus 绑定自定义事件,事件的回调函数留在A组件自身

export default {

	methods(){
		// 自定义绑定事件的回调函数
		rollbackFunc(data){...}
	}
	
	...
	mounted() {
		// 当页面挂载完成时给当前组件绑定自定义事件
		this.$bus.$on('xxx',this.rollbackFunc)
	}
}

② 提供数据:this.$bus.$emit('xxx',data)

  • 最好在beforeDestroy钩子中,用$off解绑当前组件所用到的事件

测试案例:

在这里插入图片描述

案例中将在App.vue中使用Child1Child2组件,Child1Child2组件互为兄弟组件,以下将展示两者如何进行通信。

src/main.js

import Vue from 'vue'
import App from './App.vue'

new Vue({
	el:'#app',
	render: h => h(App),
	beforeCreate() {
		//安装全局事件总线
		Vue.prototype.$bus = this 
	}
})

src/components/Child1.vue

<template>
	<div>
		<h1>兄弟组件通信 Child-1</h1>
		<h2>Child-1 姓名:{{name}}</h2>
		<h2>Child-1 年龄:{{age}}</h2>
	</div>
</template>

<script>
export default {
	name: "Child",
	
	data(){
		return{
			name: "Child-1",
			age: 10
		}
	},
	
	methods:{
		demo(data){
			console.log("我是 Child-1 组件,我收到的数据 = ", data);
		}
	},
	
	mounted() {
		// 当页面挂载完毕为 Child1 组件绑定事件
		this.$bus.$on("my-event", this.demo)
	},
	
	beforeDestroy() {
		// 销毁前取消 Child1 组件的绑定事件
		this.$bus.$off('my-event')
	}

}
</script>

src/components/Child2.vue

<template>
	<div>
		<h1>兄弟组件通信 Child-2</h1>
		<h2>Child-2 姓名:{{name}}</h2>
		<h2>Child-2 年龄:{{age}}</h2>
		
		<button @click="sendData">点我向Child-1发送数据</button>
	</div>
</template>

<script>
export default {
	name: "Child2",
	
	data(){
		return{
			name: "Child-2",
			age: 20
		}
	},
	
	methods:{
		sendData(){
			// 触发事件
			this.$bus.$emit("my-event", this.name);
		}
	}
}
</script>

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		
		<Child1></Child1>
		<hr>
		<Child2></Child2>
		
	</div>
</template>

<script>

import Child1  from "./components/Child1";
import Child2 from "./components/Child2";

export default {
	name: 'App',
	components: {
		Child1,
		Child2,
	}
}
</script>

在这里插入图片描述



四、消息订阅与发布

消息订阅与发布(pubsub):

  • 消息订阅与发布是一种组件间通信的方式,适用于任意组件间通信

使用步骤:

  • 安装 pubsub-js
npm i pubsub-js
  • 引入
import pubsub from 'pubsub-js'
  • 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身
export default {
	methods(){
		// 定义回调函数
		rollbackFunc(msgName, data){...}
	}
	...
	mounted() {
		this.pid = pubsub.subscribe('xxx', this.rollbackFunc);
	}
}

  • 提供数据
pubsub.publish('xxx', data)
  • 取消订阅
pubsub.unsubscribe(pid)

测试案例:

src/components/Child1.vue

<template>
	<div>
		<h1>兄弟组件通信 Child-1</h1>
		<h2>Child-1 姓名:{{name}}</h2>
		<h2>Child-1 年龄:{{age}}</h2>
	</div>
</template>

<script>
export default {
	name: "Child",
	
	data(){
		return{
			name: "Child-1",
			age: 10
		}
	},
	
	methods:{
		demo(msgName, data){
			console.log("我是 Child-1 组件,我收到的数据 = ", data);
			console.log("其中 msgName = ", msgName)
		}
	}
	
	mounted() {
		// 当页面挂载完毕 Child1 组件订阅消息
		console.log("订阅消息")
		this.pid = pubsub.subscribe("my-event", this.demo)
	},
	
	beforeDestroy() {
		//取消订阅
		pubsub.unsubscribe(this.pid ) 
	}
}
</script>

src/components/Child2.vue

<template>
	<div>
		<h1>兄弟组件通信 Child-2</h1>
		<h2>Child-2 姓名:{{name}}</h2>
		<h2>Child-2 年龄:{{age}}</h2>
		
		<button @click="sendData">点我向Child-1发送数据</button>
	</div>
</template>

<script>
export default {
	name: "Child2",
	
	data(){
		return{
			name: "Child-2",
			age: 20
		}
	},
	
	methods:{
		sendData(){
			// 发布消息
			pubsub.publish("my-event", this.name)
		}
	}
}
</script>

src/App.vue

<template>
	<div id="app">
		<img alt="Vue logo" src="./assets/logo.png">
		
		<Child1></Child1>
		<hr>
		<Child2></Child2>
		
	</div>
</template>

<script>

import Child1  from "./components/Child1";
import Child2 from "./components/Child2";

export default {
	name: 'App',
	components: {
		Child1,
		Child2,
	}
}
</script>

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值