超详细Vue组件开发(二)--组件通信

本文详细介绍了Vue.js中父子组件通信的两种主要方式:props实现父组件向子组件传递数据,以及子组件通过自定义事件向父组件发送数据。通过实例代码展示了如何使用props设置数据约束及默认值,以及如何定义和触发自定义事件,实现数据的双向流动。文章最后提供了一个综合案例,演示了props和自定义事件结合应用,实现了数据的双向绑定和动态更新。
摘要由CSDN通过智能技术生成


前言

上一篇介绍了组件的一些基础知识,主要包括组件的注册使用、全局组件与局部组件、组件的语法糖、父子组件、模板分离写法以及其他一些属性。
组件通信使得父子组件之间可以传递数据,扩展了组件的功能。本文将介绍使用props从父组件向子组件传递数据,以及通过自定义事件从子组件向父组件发送数据

在这里插入图片描述


一、子组件的props属性

子组件的props属性用于接收父组件传递的数据,主要步骤如下:

  1. 将vue实例作为父组件,注册其子组件
  2. 在子组件的props属性中定义接收父组件数据的变量
  3. 在使用子组件时,v-bind绑定对应的父子组件数据变量
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>props父传子</title>
		<script src="../../vue/vue.js" type="text/JavaScript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<cpn v-bind:c_message="message" :c-movies="movies"></cpn>
		</div>

		<template id="cpn">
			<div>
				<h2>{{c_message}}</h2>
				<p>{{c_movies}}</p>
				<ul>
					<li v-for="item in c_movies">{{item}}</li>
				</ul>
			</div>
		</template>

		<script>
			/** 父传子props
			 * 1、将Vue对象(root组件)作为父组件,其中注册一个子组件cpn
			 * 2、这里注册子组件结合了语法糖、template模板分离
			 * 3、在子组件中使用props属性,用于接收父组件的数据
			 * 4、使用子组件展示父组件的数据时,需要v-bind绑定父组件数据到props变量中
			 *
			 */
			const cpn = {
				template: "#cpn",
				//props: ["c_movies", "c_message"],// 数组
				props: {
					// 1、可以限制类型
					/* c_message: String,
					c_movies: Array, */

					// 2、限制类型外还可以提供默认值
					/**
					 * default:当使用时未绑定数据,传入默认值
					 * required:表示此数据必须绑定
					 */
					c_message: {
						type: String,
						default: "默认值",
						required: true,
					},
					c_movies: {
						type: Array,
						// default数据是数组、对象时,需要用工厂函数返回
						default() {
							return ["默认数组"];
						},
					},
				},
				data() {
					return {};
				},
				methods: {},
			};
			// root组件
			const app = new Vue({
				el: "#app",
				data: {
					message: "父传子props",
					movies: ["复仇者联盟", "美国往事", "八百"],
				},
				components: {
					//cpn: cpn,
					// es6增强写法
					cpn,
				},
			});
		</script>
	</body>
</html>


二、子组件向父组件发送数据(自定义事件)

1、子组件自定义事件,触发事件调用this.$emit(“custom-event”, argv)
2、在父组件中监听子组件定义的事件,定义函数接收来自子组件的数据(这里的监听函数不需要参数,默认传入子组件emit的参数)

代码如下(示例):

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>子组件自定义事件传数据到父组件</title>
		<script src="../../vue/vue.js" type="text/JavaScript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<cpn @item-click="cpnClick"></cpn>
		</div>

		<template id="cpn">
			<div>
				<button v-for="item in categories" @click="btnClick(item)">
					{{item.name}}
				</button>
			</div>
		</template>

		<script>
			/**
			 *自定义事件触发,子组件向父组件传数据
			 *1、子组件自定义事件,触发事件调用this.$emit("custom-event", argv)
			 *2、在父组件中监听子组件定义的事件,定义函数接收来自子组件的数据(这里的监听函数不需要参数,默认传入子组件emit的参数)
			 */
			const cpn = {
				template: "#cpn",
				data() {
					return {
						categories: [
							{ id: 1, name: "热门推荐" },
							{ id: 2, name: "手机数码" },
							{ id: 3, name: "家用电器" },
							{ id: 4, name: "电脑办公" },
						],
					};
				},
				methods: {
					btnClick(item) {
						this.$emit("item-click", item); // this.$emit()子组件给父组件发送事件
					},
				},
			};

			const app = new Vue({
				el: "#app",
				data: {},
				components: {
					cpn,
				},
				methods: {
					cpnClick(item) {
						console.log(item);
					},
				},
			});
		</script>
	</body>
</html>

三、父子组件通信小案例

结合props与自定义事件完成以下需求:
1、子组件数据和input数据双向绑定;
2、input数据改变父组件数据同步改变(子组件向父组件传递)
3、num1和num2成百倍关系,一方改变另一方也变

大家可以直接复制代码运行一下,体验一下父子组件通信的案例。

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>父子组件通信案例</title>
    <script src="../../vue/vue.js" type="text/JavaScript" charset="utf-8"></script>
</head>
<body>
    <!--1、子组件数据和input数据双向绑定;
    2、input数据改变父组件数据同步改变(子组件向父组件传递)
    3、num1和num2成百倍关系,一方改变另一方也变-->
    <div id="app">
        <cpn :c_num1="num1" :c_num2="num2"
        @num1change="num1change" @num2change="num2change"></cpn>
    </div>

    <template id="myTemp">
        <div>
            <h2>父组件数据:{{c_num1}}</h2>
            <h2>子组件数据:{{dc_num1}}</h2>
            <input type="text" v-model="dc_num1">
            <h2>父组件数据:{{c_num2}}</h2>
            <h2>子组件数据dc_num2:{{dc_num2}}</h2>
            <input type="text" v-model="dc_num2">
        </div>
    </template>
    <script>
        const cpn = {
            template: '#myTemp',
            data() {
                return {
                    dc_num1: this.c_num1,
                    dc_num2: this.c_num2,
                };
            },
            props: {
                c_num1: {
                    type: Number,
                },
                c_num2: {
                    type: Number,
                },
            },
            // watch监听data数据是否改变,并传入新的值
            watch: {
                dc_num1(newValue) {
                    // emit发送的argv默认为string类型
                    this.$emit('num1change', newValue);
                    this.dc_num2 = newValue * 100;
                },
                dc_num2(newValue) {
                    this.$emit('num2change', newValue);
                    this.dc_num1 = newValue / 100;
                }
            }
        }
        const app = new Vue({
            el: '#app',
            data: {
                num1: 1,
                num2: 2,
            },
            components: {
                cpn,
            },
            methods: {
                num1change(newValue) {
                    this.num1 = parseFloat(newValue);
                },
                num2change(newValue) {
                    this.num2 = parseFloat(newValue);
                }
            },
        })
    </script>
</body>
</html>

总结

本篇介绍了props、自定义事件进行父子组件通信的方法,并分别进行了演示,最后结合了两种方法进行父组件=>子组件,子组件=>父组件的双向通信。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值