关于Vue组件之间传值的详细分析

一、父组件向子组件传值

子组件要得到父组件传递而来的值,需要使用props: 来接受,而props可以接收数组和对象,所以我将从数组方法和对象方法分别阐述。

首先我们在new Vue内,构建一个局部的组件,(1) 先全局定义MyTest组件,(2) 然后在new Vue内注册组件,(3) 之后就可以通过标签形式调用注册的组件。我在这里定义组件使用的是抽离组件模板的方法定义的组件。

<body>
    <div id="testPtoC">
        <my-test></my-test>
    </div>
</body>
<template id="mytest">
    <div>这是父组件向子组件传值测试</div>
</template>
<script>
const MyTest = {
 	template: "#mytest"
}
new Vue({
    el: "#testPtoC",
    data: {
    },
    components: {
        "my-test": MyTest
    }
})
</script>

之后来步入正题父组件如何向子组件传值:
第一步: 我们可以在父组件调用子组件的地方,添加一个 自定义属性,而属性值就是你将要传递给子组件的值。

<div id="testPtoC">
	<my-test test="测试"></my-test>
</div>

tips:如果属性值为 NumberBoolean或者是 变量,则需要使用 绑定属性

<div id="testPtoC">
	<my-test test="测试" :num="10" :flag="true" :tip="tips"></my-test>
</div>

第二步:在子组件定义的时候,我们给他添加一个 props: 选项, props: 可以是 数组[ ] 也可以是 对象{ }

<script>
const MyTest = {
 	template: "#mytest",
 	// props: []	//数组
 	// props: {}	//对象
}
</script>

1.父向子传值的数组方法

第二步中如果是用 数组方法接收,那么数组中的元素,即为父组件调用子组件中 自定义的属性名,在这里就是"test",“num”, “flag”,“tip”。

<script>
new Vue({
    el: "#testPtoC",
    data: {
    	tip: "测试数据"
    },
    components: {
        "my-test": MyTest
    }
})
const MyTest = {
 	template: "#mytest",
 	//	props: ["test"],
 	props: ["test", "num", "flag", "tip"]
}
</script>

通过属性名我们就可以在子组件中获取到值:

<template id="mytest">
    <!-- <div>这是父组件向子组件传值测试 --- {{ test }}</div> -->
    <div>这是父组件向子组件传值测试 --- {{ test }} --- {{ num }} --- {{ flag }} --- {{ tip }}</div>
</template>

浏览器显示结果:
浏览器显示

2.父向子传值的对象方法

第二步中如果用的是 对象的方法接收,那么又可以分为两种写法。
写法一:props: 接收的 对象中的键key,即为父组件调用子组件中 自定义的属性名
value则为传入值的数据类型。

<script>
const MyTest = {
 	template: "#mytest",
 	props: {	//数据类型记得大写开头
        test: String,
        num: Number,
        flag: Boolean,
        tip: String
    }
}
</script>

这种写法可以验证传入的值的数据类型。(显示结果同数组方法)
我举个数据类型错误的例子:将num: Number的数据类型改为String类型,则会有如下警告:译文(属性“num”的类型检查失败。需要值为“10”的字符串,得到值为10的数字)
报警告

写法二:props: 接收一个 对象,对象中的键key,为父组件调用子组件中 自定义的属性名;value又是一个 对象,可以在该对象中添加两个键值对,如下所示:(type表示数据类型,default表示属性的默认设置)

<script>
const MyTest = {
 	template: "#mytest",
 	props: {
        test: {
            type: String,
            default: "这是默认测试"
        },
        num: {
            type: Number,
            default: 1130
        },
        flag: {
            type: Boolean,
            default: false
        },
        tip: {
            type: String,
            default: "这是默认备注"
        },
        obj: {
            type: Object,
            default: function() {
                return {user: "cxh"}
            }
        }
    }
}
</script>

以下是在父组件中设置属性值与未设置属性值的对比:

<body>
    <div id="testPtoC">
        <my-test test="测试" :num="10" :flag="true" :tip="tips" :obj="{key: 'value'}"></my-test>
        <my-test></my-test>
    </div>
</body>
<template id="mytest">
    <div>这是父组件向子组件传值测试--- {{ test }} --- {{ num }} --- {{ flag }} --- {{ tip }} --- {{ obj }}</div>
</template>

浏览器显示结果:
浏览器显示
【注意】 如果数据类型为一个对象或者是数组,默认值应该为一个函数。

二、子组件向父组件传值

第一步: 父组件在调用子组件的地方,给它绑定一个自定义的 事件不要加()

<body>
    <div id="testCtoP">
        <my-test @myevent="getData"></my-test>
    </div>
</body>

第二步: 在子组件中,利用组件自己的事件或者是生命周期钩子函数触发 this.$emit(“事件名”, “子向父传递的值”)
这里又有两种写法,我都介绍一下:

1. 写法一: 利用组件自定义的method中实现值的传递

在子组件处绑定一个点击事件sendData来触发传值操作

	<template id="mytest">
    	<div @click="sendData">这是子组件向父组件传值测试 </div>
	</template>

在子组件的methods中调用sendData,并调用this.$emit(“事件名”, “子向父传递的值”)来实现

<script>
	const MyTest = {
        template: "#mytest",
        methods: {
            sendDate() {
                this.$emit("myevent", "这是子向父传递的值")
            }
        }
    }
</script>

2. 写法二: 利用vue的生命周期钩子函数实现值的传递

	<template id="mytest">
    	<div>这是子组件向父组件传值测试 </div>
	</template>

直接在mounted()函数中调用this.$emit(“事件名”, “子向父传递的值”)来实现

<script>
    const MyTest = {
        template: "#mytest",
        mounted() {
            this.$emit("myevent", "这是子向父传递的值")
        }
    }
</script>

第三步: 在父组件选项methods中实现此事件,默认参数为从子组件中获取的值

<script>
    new Vue({
        el: "#testCtoP",
        data: {
        },
        methods: {
            getData(value) {
                console.log(value)
            }
        },
        components: {
            "my-test": MyTest
        }
    })
</script>

浏览器显示结果:(在浏览器的控制器中打印)
写法一需要在点击后打印该语句,写法二直接打印。
浏览器显示

三、非父子组件之间的传值

最后我在来说一下非父子组件之间的传值,笨办法就是:找到需要传值的两个组件之间的关系,然后通过父子之间的传值,多次传值达到我们所需的结果。这里就不谈这个方法。我要说的是通过中央事件总线来传值。
首先,先构建两个组件,我们要实现的效果,是点击组件add,来使组件count中的num+1。

<body>
    <div id="testF">
        <my-add></my-add>
        <my-count></my-count>
    </div>
</body>
<template id="add">
    <button @click="add">add1</button>
</template>
<template id="count">
    <div>
        点击次数:{{ num }}
    </div>
</template>
<script>
    const Add = {
        template: "#add"
    }

    const Count = {
        template: "#count",
        data() {
            return {
                num: 0
            }
        }
    }
    
    new Vue({
        el: "#testF",
        components: {
            "my-add": Add,
            "my-count": Count        
        }
    })
</script>

【注意】 组件数据初始化为一个data函数,如果data为 对象的话,多次调用之后会相互之间有影响,所以使用 函数确保数据间相互独立,不会影响。本例子中未体现,只是用到了data函数初始化数据,就提点一下。

那么我们如何使用所谓的中央事件总线来实现呢我们的需求呢?

我们可以定义一个 car 用于装载两个组件之间需要传递的数据。
可以在定义组件前先将其定义好:

    const car = new Vue;

接下来分为两步:
第一步:我们给要发送数据的组件,通过执行add事件调用car.emit(“发送数据的信号”,data),将它 “装载” 到我们定义的"car" 上.

     const Add = {
        template: "#add",
        methods: {
            add() {
                car.$emit("addEvent", 1);
            }
        }
    }

第二步:找到我们需要接受数据的组件,通过car.$on(“接受数据的信号”,function() { }),取到"car"上发送来的数据。
tips:一般接受数据都使用生命周期钩子函数。

     const Count = {
        template: "#count",
        data() {
            return {
                num: 0
            }
        },
        mounted() {
            let that = this;//函数内部this指向改变了,所以定义一个that用于获得data中的num
            car.$on("addEvent", function(data){
                that.num += data;
            })
        }
    }

function函数中参数就是用car.emit(“发送数据的信号”,data)中的data,前提是自定义的*“发送数据的信号""接受数据的信号”*一致,这样就保证了两个组件之间可以进行传值操作。

浏览器显示结果:

初始:
初始数据
点击三次之后:
点击三次后
显而易见,我们需要实现的两个非父子组件之间的传值已经实现了。

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值