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


    一、 props配置项

    props配置项:

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

    • 传递数据:

    • 接收数据:

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

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

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

    props:{
    	name:{
    		type:String, 	//类型
    		required:true,  //必要性
    		default:'划水艺术家'  //默认值
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试案例:

    src/App.vue

    <template>
    	<div id="app">
    		<img alt="Vue logo" src="./assets/logo.png">
    		
    		<Student name="划水艺术家" age="20">Student>
    	div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述


    2. 子组件向父组件通信

    ****

    ① 基础方法

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

    测试案例:

    src/components/Child.vue

    <template>
    	<div>
    		<h1>子组件向父组件通信h1>
    		<h2>姓名:{{name}}h2>
    		<h2>年龄:{{age}}h2>
    		<button @click="childFunc">点我年龄 + 1 并将姓名传送至父组件 Appbutton>
    	div>
    template>
    
    <script>
    export default {
    	name: "Child",
    	
    	// 其中 func 为父组件向子组件传递的方法
    	props:['name', 'age', 'func'],
    	
    	methods:{
    		childFunc(){
    			// 调用父组件传递的方法
    			this.func(this.name);
    		}
    	}
    }
    script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述


    ② 自定义事件

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

    组件的自定义事件:

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

    • 绑定自定义事件:

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

    <Child @my-event="func"/><Child v-on:my-event="func"/>
    
    • 1
    • 2
    • 3

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

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

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

    • 解绑自定义事件:

    // 解绑一个自定义事件
    // this.$off('my-event')
    
    // 解绑多个自定义事件
    // this.$off(['my-event'])
    
    // 解绑所有自定义事件
    this.$off()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 组件上也可以绑定原生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 并将姓名传送至父组件 Appbutton>
    	div>
    template>
    
    <script>
    export default {
    	name: "Child",
    	
    	props:['name', 'age'],
    	
    	methods:{
    		childFunc(){
    			// 触发 Child 组件实例身上的 my-event 事件
    			this.$emit("my-event", this.name);
    		}
    	}
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    src/App.vue

    <template>
    	<div id="app">
    		<img alt="Vue logo" src="./assets/logo.png">
    		
    		
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述


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

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

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

    src/App.vue

    <template>
    	<div id="app">
    		<img alt="Vue logo" src="./assets/logo.png">
    		
    		
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    ④ 自定义事件的解绑

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

    src/components/Child.vue

    <template>
    	<div>
    		<h1>子组件向父组件通信h1>
    		<h2>姓名:{{name}}h2>
    		<h2>年龄:{{age}}h2>
    		<button @click="childFunc">点我年龄 + 1 并将姓名传送至父组件 Appbutton>
    		
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    三、全局事件总线

    全局事件总线(GlobalEventBus):

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

    使用步骤:

    • 安装全局事件总线:
    new Vue({
    	...
    	beforeCreate() {
    		//安装全局事件总线 
    		Vue.prototype.$bus = this 
    	},
    	...
    }) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 使用事件总线:

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

    export default {
    
    	methods(){
    		// 自定义绑定事件的回调函数
    		rollbackFunc(data){...}
    	}
    	
    	...
    	mounted() {
    		// 当页面挂载完成时给当前组件绑定自定义事件
    		this.$bus.$on('xxx',this.rollbackFunc)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ② 提供数据: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 
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    src/components/Child1.vue

    <template>
    	<div>
    		<h1>兄弟组件通信 Child-1h1>
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    src/components/Child2.vue

    <template>
    	<div>
    		<h1>兄弟组件通信 Child-2h1>
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述



    四、消息订阅与发布

    消息订阅与发布(pubsub):

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

    使用步骤:

    • 安装 pubsub-js
    npm i pubsub-js
    
    • 1
    • 引入
    import pubsub from 'pubsub-js'
    
    • 1
    • 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身
    export default {
    	methods(){
    		// 定义回调函数
    		rollbackFunc(msgName, data){...}
    	}
    	...
    	mounted() {
    		this.pid = pubsub.subscribe('xxx', this.rollbackFunc);
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 提供数据
    pubsub.publish('xxx', data)
    
    • 1
    • 取消订阅
    pubsub.unsubscribe(pid)
    
    • 1

    测试案例:

    src/components/Child1.vue

    <template>
    	<div>
    		<h1>兄弟组件通信 Child-1h1>
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    src/components/Child2.vue

    <template>
    	<div>
    		<h1>兄弟组件通信 Child-2h1>
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述


  • 相关阅读:
    Glide缓存核心原理详解
    自动化测试 | 多个自动化测试用例?多个自动化测试数据怎么管理?资深测试总结
    leetcode解题思路分析(一百五十)1305 - 1312 题
    中级C++:哈希
    荣耀进击背后的「韧性力量」
    【无标题】
    代驾APP_第一章_项目环境搭建_第二节
    【毕业设计源码】基于小程序蔬菜/零食商城系统
    做一个Springboot文件上传-阿里云
    MybatisPlus 一些技巧
  • 原文地址:https://blog.csdn.net/qq_51938362/article/details/126248000