前言:组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说组件之间有这几种关系:父子、兄弟、隔代。
针对不同的使用场景,如何选择行之有效的通信方式?这是我们所要探讨的主题。
一、父组件向子组件传值
接下来我们通过一个例子,说明父组件App.vue如何向子组件传递值:在子组件Users.vue中如何获取父组件
1. App.vue代码:
//App.vue父组件
<template>
<div id="app">
<users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名
</div>
</template>
<script>
import Users from "./components/Users"
export default {
name: 'App',
data(){
return{
users:["Henry","Bucky","Emily"]
}
},
components:{
"users":Users
}
}
2. Users.vue代码:
//users子组件
<template>
<div class="hello">
<ul>
<li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props:{
users:{ //这个就是父组件中子标签自定义名字
type:Array,
required:true
// 必传,且为 Array 类型
}
}
}
</script>
3.注意
(1)所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。
(2)另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告
二、子组件向父组件传值(通过事件形式)
在组件的模板表达式中,可以直接使用 $emit
方法触发自定义事件 (例如:在 v-on
的处理函数中):$emit
中第一个参数是触发自定义事件名,第二个是给自定义事件传递的内容从而实现子组件向父组件传值
<!-- MyComponent -->
<button @click="$emit('someEvent', '我是帅哥')">click me</button>
$emit()
方法在组件实例上也同样以 this.$emit()
的形式可用:
export default {
methods: {
submit() {
this.$emit('someEvent', '我是帅哥')
}
}
}
父组件可以通过 v-on
(缩写为 @
) 来监听事件:
<MyComponent @some-event="callback" />
三、非父子组件传值
1.$emit/$on :这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。
(1)this.$emit(‘自定义事件名’,要传送的数据),触发当前实例上的事件,要传递的数据会传给监听器
(2)this.$on ( ′ 事 件 名 ′ , callback ) callback 回 调 emit要传送的数据,监听当前实例上自定义事件
2.provide/inject:Vue2.2.0新增API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。一言而蔽之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
假设有两个组件: A.vue 和 B.vue,B 是 A 的子组件
// A.vue
export default {
provide: {
name: '浪里行舟'
}
}
// B.vue
export default {
inject: ['name'],
mounted () {
console.log(this.name); // 浪里行舟
}
}
可以看到,在 A.vue 里,我们设置了一个 provide: name,值为 浪里行舟,它的作用就是将 name 这个变量提供给它的所有子组件。而在 B.vue 中,通过 inject
注入了从 A 组件中提供的 name 变量,那么在组件 B 中,就可以直接通过 this.name 访问这个变量了,它的值也是 浪里行舟。这就是 provide / inject API 最核心的用法。
注意:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的