Javascript

Vue基础之非父子组件间传值

本文主要是介绍Vue基础之非父子组件间传值,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

运用的场合

我们已经知道,从父组件向子组件传值可以通过在子组件中添加props实现,而子组件向父组件传值主要通过向外触发函数。

当我们的页面采用三层嵌套,颜色由浅到深并对应图中1,2,3。

那么如果我们想沿着蓝色的线传递值,是否需要将值从1-> 2-> 3这样;如果我们想沿着紫色的线传递值,是否要将值从3 ->2 ->1 ->2 -> 3呢。这些过于麻烦,都不需要!

我们需要使用: Bus/总线/发布订阅模式/观察者模式(反正都是一个意思) ,便可以实现非父子关系的传值。

基本格式:

<body>
	<div id="root">
		<child></child>
		<child></child>
	</div>

	<script type="text/javascript">
		Vue.component('child',{
			template:'<div>child</div>'
		})

		var vm=new Vue({
			el:'#root'
		})
	</script>
</body>
复制代码

这里我们先写入一个最简单的父子组件传值。

<div id="root">
        <child content='Aston'></child>
        <child content='Martin'></child>
</div>

<script type="text/javascript">
    Vue.component('child',{
        props:{
            content:String
        },
        template:'<div>{{content}}</div>'
    })

    var vm=new Vue({
        el:'#root'  
    })
</script>
复制代码

用一个例子实现传值

我现在想实现如果点击任何一个文字,另一个文字也会变成我点击的文字,其实就是改变未点击文字的content值。这就属于非父子组件的兄弟组件传值。

1. 在组件中添加基本的点击事件

Vue.component('child',{
    props:{
        content:String
    },
    template:'<div @click="handleclick">{{content}}</div>',
    methods:{
        handleclick:function(){
            alert(this.content)
        }
    }
})
复制代码

2. 添加总线属性:

Vue.prototype.bus = new Vue()
复制代码

这里是给Vue的每个prototype上挂载一个bus属性,然后将bus属性指向vue实例。由于我们的每一个实例都是通过Vue创建的,因此我们每个组件上都会有bus属性。

3. 修改点击事件

handleclick:function(){
    this.bus.$emit('change',this.content)
}
复制代码

由于第一步已经给所有实例添加了bus属性,这里调用bus$emit 方法向外(总线)触发事件“change”,并携带参数“this.content”。

这个bus顾名思义,可以理解为“公交车/总线”,作为一个公共区域被多方监听并触发多个事件。

4. 使用生命周期钩子

mounted:function(){
    this.bus.$on{this.bus.$on('change',function(msg){
        this.content = msg;
    })
}
复制代码

mounted就是实例被挂载的时候执行的函数,并在这个函数中实现监听bus上触发的事件。

但注意,这个方法加入后期望效果仍不能实现!

原因是:我们使用了两个子组件,并且都具有“点击向总线触发”和“监听总线”这两个方法。所以如果我点击第一个组件,他向外触发事件的同时进行监听,这就会导致this分别指向各自本身,第一个组件的this都指向自己,第二个组件同样。这样就没法做到把第一个this指向的值传递给第二个组件。

5. 记录下点击的this

我们在mounted函数中进行修改:

mounted:function(){
    this.bus.$on{this.bus.$on('change',function(msg){
    var loc=this
        loc.content = msg;
    })
}
复制代码

我们在mounted(已挂载函数)函数中声明一个变量“loc”用以保存我点击的那个this

这样我们的效果就实现了,但是当我们打开控制台,会发现报错:避免子组件改变父组件的值。也就是说我们一直在改变父组件所传递的content,这是不应该的。

6. 保存一份父组件的值

由于上面的报错,我们在组件中添加data来保存父组件的值:

data:function(){
    return {
        selfcontent:this.content
    }
}
复制代码

并将其他部分的content进行替换。

7. 全部代码

<body>
	<div id="root">
		<child content='Aston'></child>
		<child content='Martin'></child>
	</div>

	<script type="text/javascript">

		Vue.prototype.bus = new Vue()

		Vue.component('child',{
			data:function(){
				return {
					selfcontent:this.content
				}
			},
			props:{
				content:String
			},
			template:'<div @click="handleclick">{{selfcontent}}</div>',
			methods:{
				handleclick:function(){
					this.bus.$emit('change',this.selfcontent)
				}
			},
			mounted:function(){
				var loc=this;
				this.bus.$on('change',function(msg){
					loc.selfcontent=msg;
				})
			}
		})

		var vm=new Vue({
			el:'#root'
		})
	</script>
</body>
复制代码

总结

我们最后再捋一遍整个过程:我们点击第一个文字盒子,触发组件内“handleclick”事件,此事件向总线触发“change”事件并将第一个盒子中的内容作为参数传递,这时两个盒子都执行mounted函数,将指向各自组件的this保存在变量loc中,然后监听的“change”事件被触发,将事件所携带的参数(指向第一个盒子的内容)赋给指向各自的内容。第一个盒子赋给自己不变,第二个盒子实现第一个盒子的值赋给自己。

这篇关于Vue基础之非父子组件间传值的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!