浅谈vue中组件通信的几种方式

vue中组件传值主要分为三种:父传子、子传父、兄弟组件传值、以及深层嵌套的组件之间的传值

父传子是通过props的方式传递

props可以是字符串数组和对象,用于接收来自父组件的数据

父组件中通过v-bind的方式传递数据

<title :msg="list"></title>
// 父组件中通过v-bind的方式传递数据

子组件通过props接收数据,props 可以是数组或对象,用于接收来自父组件的数据,props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。

// 数组方式
porps: ['msg']

// 对象方式可以进行数据的验证
props: {
	msg: {
		type: OBject, // 定义数据的类型,String、Number、Boolean、Array、Object、Date、Function、Symbol
		require: true,// Boolean  定义该prop是否是必填项
		default: {}, // any 为该prop定义一个默认值
		validator: function() {} // Function 自定义验证函数会将porp的值作为唯一参数带入
	}
}
  1. props中声明的数据与组件data函数return的数据主要的区别就是props的数据来自父级,而data中的数据是组件自己的数据,作用域是组件本身。这两种数据斗可以在tempalet及计算属性computed和methods方法中使用。

  2. 如果在父组件中传递数据时不使用v-bind绑定传递数据,传递到子组件的数据就仅仅是一个字符串

    // 父组件
    <title msg="{ name: 小明 }" />
    
    // 子组件
    <template>
    	<div>{{ msg.length }}<div> // 输出的msg长度为14(加上左右的空格),
    <template/>
    
    props: ['msg']
    
  3. vue 2.x 中通过props传递的数据是单向向下的,就是说父组件中的数据变化可以影响子组件中的数据变化,但子组件却不能影响父组件。vue 1.x中提供了.sync的修饰符来支持双向绑定。

  4. 一般修改prop的情况有两种:一种子组件把父组件传递过来的初始值作为局部数据使用(子组件data中声明一个数据来引用父组件中传递的prop),另一种就是prop作为传入后,有子组件处理成其他数据输出(使用计算属性处理)当prop是数组和对象时,在子组件中改变是会影响父组件的

子传父使用自定义事件进行传递

v-on指令除了监听DOM事件外,还可以用于组件之间的自定义事件。vue允许在子组件用 e m i t ( ) 来 触 发 事 件 , 父 组 件 用 emit()来触发事件,父组件用 emit()on()来监听子组件的事件

// 子组件
<button @click="addNum">加</button>

data() {
	return: {
		childNum: 0	
	}
},
methods: {
	addNum() {
		this.num ++;
		this.$emit('addNum', this.childNum) // 第一个参数自定义事件的名字,第二个参数是想要传递的参数
	}
}


//父组件
 <div @addNum="getNum">{{ parentNum }}</div>

data() {
	return: {
		parentNum: 0
	}
}
methods: {
	getNum(num) {
		this.parentNum = num
	}
}

vue 2.x还可以在自定义子组件上使用v-model来实现数据的传递

<div id='app'>
	<p>{{ parentNum }}</p>
	<child v-model="parentNum"/>
</div>
<script>
	Vue.component{'child', {
		template: '<button @click="addNum">加</button>',
		data() {
			return: {
				num: 0
			}
		},
		methods: {
			addNum() {
				this.num ++
				this.$emit('input', this.num)
			}
		}
	}};
	
	var app = new Vue({
		el: '#app',
		data: {
			parentNum
		}
	})
</script>

实现这样具有双向绑定的v-model组件要满足两个条件:接收一个value属性;在有新的value时触发input事件

非父子组件间传值

非父子组件一般有兄弟传值和跨多级组件。在vue 1.x中除了 e m i t ( ) 方 法 外 , 还 提 供 有 emit()方法外,还提供有 emit()dispatch()和 b r o a d d c a s t ( ) 这 两 个 方 法 。 broaddcast()这两个方法。 broaddcast()dispatch()用于向上级派发事件,只要是它的父级都可以用Vue实例中events选项接收,$broadcast()与其相反。这两种方法在Vue 2.x中已废除

在Vue.js 2.x中,推荐使用使用一个空的Vue实例作为中央事件总线(bus),用它来触发事件和监听事件,巧妙而轻量的实现任何组件间的通信,包括父子、兄弟 、跨级。当我们项目较大时,也可以选择更好的状态管理工具Vuex,下面主要说使用bus的实现

let eventBus = new Vue()
eventBus.$emit('事件名', 数据)
eventBus.$on('事件名', data => {})

例:

<div id="app">
	<my-a></my-a>
	<my-b></my-b>
	<my-c></my-c>
</div>
<template id="a">
  <div>
    <h3>A组件:{{name}}</h3>
    <button @click="send">将数据发送给C组件</button>
  </div>
</template>
<template id="b">
  <div>
    <h3>B组件:{{age}}</h3>
    <button @click="send">将数组发送给C组件</button>
  </div>
</template>
<template id="c">
  <div>
    <h3>C组件:{{name}},{{age}}</h3>
  </div>
</template>

var EventBus = new Vue();//定义一个空的Vue实例
var A = {
	template: '#a',
	data() {
	  return {
	    name: 'tom'
	  }
	},
	methods: {
	  send() {
	    EventBus.$emit('data-a', this.name);
	  }
	}
}
var B = {
	template: '#b',
	data() {
	  return {
	    age: 20
	  }
	},
	methods: {
	  send() {
	    EventBus.$emit('data-b', this.age);
	  }
	}
}
var C = {
	template: '#c',
	data() {
	  return {
	    name: '',
	    age: ""
	  }
	},
	mounted() {//在模板编译完成后执行
	 EventBus.$on('data-a',name => {
	     this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
	 })
	 Event.$on('data-b',age => {
	     this.age = age;
	 })
	}
}
var vm = new Vue({
	el: '#itany',
	components: {
	  'my-a': A,
	  'my-b': B,
	  'my-c': C
	}
});
</script>

除了中央事件总线bus外,还有两种方法实现组件通信:父链和组件索引

父链:在子组件中使用this. p a r e n t 可 以 直 接 访 问 该 组 件 的 父 例 或 组 件 , 父 组 件 也 可 以 通 过 t h i s . parent可以直接访问该组件的父例或组件,父组件也可以通过this. parent访this.children访问它所有的子组件,而且可以递归向上或向下无限访问,直到跟实例或最内层的组件

<div id="app">
	{{ message }}
	<component-a></component-a>
</div>

<script>
	Vue.component('component-a', {
		template: '<button @click="handleEvent">通过父链直接修改数据</button>'
		methods: {
			handleEvent() {
				// 访问父链后,可以做任何操作,比如直接修改数据
				this.$parent.message = '来自组件component-a的内容'
			}
		}
	})
	
	var app = new Vue({
		el: '#app',
		data: {
			message: ''
		}
	})

</script>
// 尽管Vue允许这样操作,但业务中,子组件应该尽可能地避免依赖父组件的数据,更不该主动修改它的数据

子组件索引

当子组件较多时,通过this.$children来一一遍历我们需要的组件实例是比较困难的,Vue提供了组件索引的方法,用特殊的属性ref来为组件指定索引名称(Vue 2.x将v-el和v-ref合并为了ref)

<div id="app">
	<button @click="handleRef">通过ref获取子组件实例</button>
	<component-a ref="comA"></component-a>
</div>
<script>
	Vue.component('component-a', {
		template: '<div>子组件</div>',
		data() {
			return {
				message: '子组件内容'
		}
	})
</script>
var app = new Vue({
	el: '#app',
	methods: {
		handleRef() {
			var msg = this.$refs.comA.message
			console.log(msg)
		}
	}
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值