1. props和$emit
最简单常用的方式
目录结构
// index.vue
<template>
<div>
<h2>父组件中</h2>
输入向子组件传值<input type="text" v-model="foo">
<child-com :foo="foo" @out="getMsg"></child-com>
<h2>子组件信息</h2>{{childMsg}}
</div>
</template>
<script>
const childCom = () => import('./components/child')
export default {
components: {
childCom
},
data() {
return {
foo: '',
childMsg: ''
}
},
methods: {
getMsg(v) {
this.childMsg = v
}
}
}
</script>
// child.vue
<template>
<div>
<h2>子组件中</h2> {{foo}}
<br/>
<button @click="sendMsg">点击向父组件传值</button>
</div>
</template>
<script>
export default {
props: ['foo'],
methods: {
sendMsg() {
this.$emit('out', 'msg')
}
}
}
</script>
效果图
2. vuex
3. 依赖注入
使用场景
当组件嵌套过多,而且所有组件都需要使用根组件(包括但不限于)的某一些内容时(数据或方法),使用依赖注入会比普通的传值更加方便
使用
// 依赖注入一个getMap方法
provide: function () {
return {
getMap: this.getMap
}
}
然后在任何子组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的属性:
inject: ['getMap']
相比于$parent,选择依赖注入的好处
使用依赖注入可以让我们免于暴露整个根组件信息,具体有两点
- 祖先组件不需要知道哪些后代组件使用它提供的属性
- 后代组件不需要知道被注入的属性来自哪里
4. 使用$emit/$on,模拟发布订阅模式
这里需要利用一个空的vue对象当做事件中心,可以实现组件间的通讯
目录结构
// event.js创建一个新的vue实例
import Vue from 'vue'
const Event = new Vue()
export default Event
// index.vue
<template>
<div>
父组件 {{msg}}
<child-com01></child-com01>
<child-com02></child-com02>
</div>
</template>
<script>
import Event from './components/event'
const childCom01 = () => import('./components/child01')
const childCom02 = () => import('./components/child02')
export default {
components: {
childCom01,
childCom02
},
data() {
return {
msg: ''
}
},
mounted() { // 因为不知道什么时候会触发方法,所以一般会选择在created或者是mounted的时候绑定
Event.$on('getMsg', v => this.msg = v) //箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
}
}
</script>
// child01.vue
<template>
<div>
子组件01 {{msg}}
</div>
</template>
<script>
import Event from './event'
export default {
mounted() {
Event.$on('getMsg', v => this.msg = v)
},
data() {
return {
msg: ''
}
}
}
</script>
// child02.vue
<template>
<div>
<h2>子组件02</h2>
<button @click="sendMsg">to 父组件和兄弟组件</button>
</div>
</template>
<script>
import Event from './event'
export default {
methods: {
sendMsg() {
Event.$emit('getMsg', 'child02的数据')
}
}
}
</script>
注意: 在使用$on绑定事件之后,需要主动销毁事件
例如
beforeDestroy () {
Event.$off('getMsg')
}
5. 使用$attrs/$listeners
在父组件通过v-bind绑定,但是在子组件中未被props声明的属性可以通过$attrs获取到。
$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器
// index.vue
<template>
<div>
父组件
<child-com01 :msg1="msg1" :msg2="msg2" :msg3="msg3" :msg4="msg4" @indexfuc="indexfuc" @indexfuc2="indexfuc2" @indexfuc3="indexfuc3"></child-com01>
</div>
</template>
<script>
const childCom01 = () => import('./components/child01')
export default {
components: {
childCom01
},
data() {
return {
msg1: 'm1',
msg2: 'm2',
msg3: 'm3',
msg4: 'm4'
}
},
methods: {
indexfuc() {
console.log('根组件方法1')
},
indexfuc2() {
console.log('根组件方法2')
},
indexfuc3() {
console.log('根组件方法3')
}
}
}
</script>
// child01.vue
<template>
<div>
子组件01收到的数据 {{$attrs}}
props接收的数据{{msg1 + ' ' + msg2}}
<child-com02 v-bind="$attrs" v-on="$listeners"></child-com02>
</div>
</template>
<script>
const childCom02 = () => import('./child02')
export default {
components: {
childCom02
},
props: ['msg1', 'msg2'],
mounted() {
console.log(this.$attrs, '---child1中')
console.log(this.$listeners, '---child1中')
this.$listeners.indexfuc2()
}
}
</script>
// child02.vue
<template>
<div>
子组件02收到的数据 {{$attrs}}
</div>
</template>
<script>
export default {
mounted() {
console.log(this.$listeners, '---child02中')
this.$listeners.indexfuc3()
}
}
</script>
这里的child02是child01的子组件,三个组件是嵌套关系,child02可以拿到全部的属性和方法
6. $refs和$parent、$children
使用ref给组件赋值一个ID
<base-input ref="usernameInput"></base-input>
之后使用this.$refs.usernameInput来访问这个组件
this.$refs.usernameInput
或者在组件中使用来获取数据
this.$parent
this.$children
但是这几种无法实现跨级或兄弟组件之间传递消息,在使用过程中,应该酌情使用以上几种方法