参考:【Vue2从入门到精通】深入浅出,带你彻底搞懂Vue2组件通信的9种方式_vue2组件通信方式-CSDN博客
参考:一文搞懂Vue2中的组件通信_vue.js_脚本之家
Vue组件间通信分类
Vue组件间通信主要指以下 34类:
①父子组件通信②隔代组件通信③兄弟组件通信④不相关组件传值
下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。
1.props / $emit
①父组件向子组件传值
下面通过一个例子说明父组件如何向子组件传递数据:在子组件child.vue中如何获取父组件parents.vue中的数据obj:
javascript
// 父组件 parents.vue
<template>
<div >
<child :obj="obj"></child>
</div>
</template>
<script>
import child from './child .vue'
export default {
components: { child },
data() {
return {
obj: ['obj1', 'obj1','obj1', 'obj1']
}
}
}
</script>
// 子组件 child.vue
<template>
<div>
<span v-for="(item, index) in obj" :key="index">{{item}}</span>
</div>
</template>
<script>
export default {
props: ['obj']
}
</script>
②子组件向父组件传值
使用$emit,下面使用例子说明:
javascript
// 父组件 parents.vue
<template>
<div >
<child :list="list" @ownIndex="ownIndex"></child >
<p>{{currentIndex}}</p>
</div>
</template>
<script>
import child from './child .vue'
export default {
components: { child },
data() {
return {
currentIndex: -1,
list: ['1', '2','3', '4']
}
},
methods: {
ownIndex(currentIndex ) {
this.currentIndex = currentIndex
}
}
}
</script>
//子组件 child.vue
<template>
<div>
<div v-for="(item, index) in list" :key="index" @click="emitIndex(index)">{{item}}</div>
</div>
</template>
<script>
export default {
props:['list']
methods: {
emitIndex(index) {
this.$emit('ownIndex', index)
}
}
}
</script>
2.parent / children
适用于父子组件通信
parent / children:访问父 / 子实例
javascript
// 父组件中
<template>
<div >
<div>{{message}}</div>
<childA ></childA>
<button @click="changeChildA">点击改变子组件值</button>
</div>
</template>
<script>
import childA from './childA .vue'
export default {
components: { childA },
data() {
return {
message: 'hello world'
}
},
methods: {
changeChildA() {
// 获取到子组件A
this.$children[0].messageA = 'this is new value'
}
}
}
</script>
// 子组件中childA
<template>
<div >
<span>{{messageA}}</span>
<p>获取父组件的值为: {{parentVal}}</p>
</div>
</template>
<script>
export default {
data() {
return {
messageA: 'this is old'
}
},
computed:{
parentVal(){
return this.$parent.message;
}
}
}
</script>
3.$ref
父组件通过$ref拿到子组件实例,通过实例修改子组件数据:
javascript
<template>
<div>
<p>我是父亲</p>
<Child ref="childRef" />
</div>
</template>
<script>
import Child from "./child.vue";
export default {
components: {
Child,
},
mounted() {
this.$refs.childRef.childMsg = "不你不是";
},
};
</script>
// 子组件child等着被改就行
<template>
<div>
<p>我是子组件</p>
<span>{{ childMsg }}</span>
</div>
</template>
<script>
export default {
data() {
return {
childMsg: "我是子组件数据",
};
},
};
</script>
4.EventBus (emit / on)
适用于隔代组件通信,eventBus也有不方便之处, 当项目较大,就容易造成难以维护的灾难,下面分步骤讲解:
①初始化
javascript
new Vue({
router,
store,
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus=this //安装全局事件总线,所有组件都能看到$bus
}
}).$mount('#app')
②发送事件
javascript
this.$bus.$emit("uptOrderDialogVisible", true)
③接收事件
javascript
this.$bus.$on("uptOrderDialogVisible", (e) => {console.log(e)})
④销毁事件
javascript
this.$bus.$off("uptOrderDialogVisible");
5. attrs / listeners
javascript
// 父组件parents.vue
<template>
<div>
<span>{{ dadData }}</span>
<Son :dadData="dadData" @changeDadData="changeDadData" @keyup="someKeyUp" />
</div>
</template>
<script>
import Son from "./son.vue";
export default {
components: {
Son,
},
data() {
return {
dadData: "父组件",
};
},
methods: {
changeDadData(newData) {
this.dadData = newData;
},
someKeyUp(e) {
console.log(e.target.value);
},
},
};
</script>
// 儿子组件son
<template>
<div>
<p>我是儿子组件</p>
<span>{{ $attrs.dadData }}</span>
<input type="text" v-on="$listeners" />
<GrandSon v-bind="$attrs" v-on="$listeners" />
</div>
</template>
<script>
import GrandSon from "./GrandSon.vue";
export default {
components: {
GrandSon,
},
mounted() {
console.log(this.$listeners);
},
};
</script>
// 孙子组件
<template>
<div>
<p>我是孙子组件</p>
<input type="text" @input="grandsonInput" />
</div>
</template>
<script>
export default {
methods: {
grandsonInput(e) {
// this.$emit("changeDadData", e.target.value); 也可以触发
this.$listeners.changeDadData(e.target.value);
},
},
};
</script>
6.provide / inject
适用于隔代组件通信,举例说明:
假设有三个组件: A.vue、B.vue、C.vue 其中 C是B的子组件,B是A的子组件
javascript
// A.vue
<template>
<div>
<comB></comB>
</div>
</template>
<script>
import comB from './comB.vue'
export default {
name: "A",
provide: {
for: "demo"
},
components:{
comB
}
}
</script>
// B.vue
<template>
<div>
{{demo}}
<comC></comC>
</div>
</template>
<script>
import comC from './comC.vue'
export default {
name: "B",
inject: ['for'],
data() {
return {
demo: this.for
}
},
components: {
comC
}
}
</script>
// C.vue
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
name: "C",
inject: ['for'],
data() {
return {
demo: this.for
}
}
}
</script>