版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
组件通信的方法:
1、props和emit
2、vuex
3、bus
4、children和parent
5、ref
props和emit()
- 说明:props和emit用于父子组件通讯,props父组件向子组件中传值,emit方法用于子组件向父组件中传值。
- 使用场景:一般用于父子组件通讯,封装公用组件中使用。
父组件
<e-test title="标题" @change="getValue"></e-test>
<script>
export default {
name:'parent',
methods:{
getValue(value){
console.log(value)
}
}
}
</script>
子组件
<template>
<div>
<p>{{title}}</p>
<button @click="toClick">点击</button>
</div>
</template>
<script>
export default {
name:'test',
props:['title'],
methods:{
toClick(){
this.$emit('change','你要传入的值')
}
}
}
</script>
vuex
- 说明:一个公共的仓库,数据改变视图也可以改变,f5刷新页面时数据会丢失
- 使用场景:用于存放用户信息、token、公用组件的数据等公用数据
vuex有5个属性,state、modules、getters、mutations、actions - state:类似data用于存储数据
- modules:用于区分不同的模块,每个模块中有除modules外的属性
- getters:类似于computed计算属性
- mutations:用于存放同步的方法
- actions:用于存放异步的方法
示例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use( Vuex )
import components from './modules/components'
const store = new Vuex.Store( {
modules: {
components
}
} )
export default store
模块中
// 所有公用组件的请求,避免组件多次重复请求统一处理
import { initData } from '@/api/data';
const components = {
state: {
params: { page: 0, size: 10 },
baseURL: process.env.VUE_APP_BASE_API,
// 物料列表
materialList: [],
materialTotal: 0
},
mutations: {
// 设置物料列表的值
setMaterialList( state, val ) {
state.materialList = val
},
setMaterialTotal( state, val ) {
state.materialTotal = val
}
},
actions: {
// 获取物料列表
getMaterialList( { commit, state } ) {
let url = 'api/material'
return new Promise( resolve => {
initData( url, state.params, state.baseURL )
.then( res => {
commit( 'setMaterialList', res.content )
commit( 'setMaterialTotal', res.totalElements )
resolve()
} )
} )
}
}
export default components
使用vuex
需要注意:mutations和actions中的方法默认是全局的,没有模块作用域限制。
import { mapState, mapActions } from "vuex";
computed: {
...mapState({
materialList(state) {
return state.components.materialList;
},
materialTotal(state) {
return state.components.materialTotal;
}
})
},
methods: {
...mapActions(["getMaterialList"]),
// 避免在table组件中使用初始化时多次请求
initComponent() {
this.$nextTick(() => {
if (this.materialTotal) {
this.total = this.materialTotal;
this.data = this.materialList;
} else {
this.getMaterialList().then(() => {
this.total = this.materialTotal;
this.data = this.materialList;
});
}
});
}
}
bus通讯
- 说明: 可以实现非父子组件通讯
- 使用场景:相对于vuex,bus通讯方式更加方便、灵活、简单、多用于单个模块内的非父子组件通信。
- 举例:B组件和C组件都在A组件中,要实现B组件和C组件之间的通讯,用bus来实现比用vuex要简单得多。
注意事项:需要在离开页面前将绑定的bus监听销毁掉
使用方法:
bus.js
import Vue from 'vue'
const bus = new Vue();
export default bus;
B组件中
import Bus from './bus.js'
export default{
beforeDestory(){
Bus.$off('test')
},
methods:{
toClick(){
Bus.$emit('test','传递的值')
}
}
}
C组件中
import Bus from './bus.js'
export default{
mounted(){
Bus.$on('test',val=>{
console.log(val)
})
}
}
parent、children通讯
- 说明:可以直接获取一级父子组件的属性和方法并且可以修改
- 使用场景:用于父子组件的通讯
子组件中
<template>
<div>{{name}}</div>
</template>
export default{
data(){
return{
name:'测试数据'
}
},
mounted(){
this.$nextTick(()=>{
console.log(this.$parent.age)
})
}
}
父组件中
<template>
<e-test ref="test"></e-test>
</template>
export default{
data(){
return{
age:23
}
},
mounted(){
this.$nextTick(()=>{
console.log(this.$children.name)
})
}
}
ref通讯
- 说明:可以获取并修改子组件中的属性和方法
- 使用场景:用于父子组件的通讯
子组件中
<template>
<div>{{name}}</div>
</template>
export default{
data(){
return{
name:'测试数据'
}
}
}
父组件中
<template>
<e-test ref="test"></e-test>
</template>
export default{
mounted(){
this.$nextTick(()=>{
console.log(this.$refs.test.name)
})
}
}