引言
Vue的两大特性:响应式和组件化。当项目体积和工程量开发到比较大的时候,一个vue文件有几千行代码的时候,这样是不利于开发和维护的,我们经常做的是抽离组件,而谈论组件,不得不考虑组件之间是如何传值的,今天我们就来探讨一下组件之间是如何传递数据的。
1、父组件向子组件通过props传递数据,子组件通过$emit(派发事件的方式)给修改父组件的数据,进而修改子组件数据
// 父组件
<template>
<div>
<div >{{title}}</div>
// 注意 .sync可以帮我们实现父组件向子组件传递的数据的双向绑定
<Item
:title.sync="title"
:pay-type="payType"
@updateMsg="handleUpdate"
>
</Item>
</div>
</template>
<script>
import Item from './components/Son.vue';
export default {
components: {Item},
data () {
return {
title: '我是父组件',
payType: 'tested',
};
},
methods: {
handleUpdate (val) {
this.payType = val;
}
}
};
</script>
// 子组件
<template>
<div>
<div>{{payType}}</div>
<el-button @click="handleClick">点我</el-button>
<el-button @click="handleClick2">再点</el-button>
<div>{{title}}</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ''
},
payType: {
type: String,
default: ''
}
},
methods: {
handleClick () {
this.$emit('updateMsg', 'testing');
},
handleClick2 () {
// 子组件是可以通过update直接去修改父组件的值的,这里不同于this.$emit触发一个方法通过修改父组件的数据进而修改子组件的数据,这里好好思考一下哦
this.$emit('update:title', '好像是能改变的');
}
}
};
</script>
如果是兄弟组件需要穿插数据呢?
或许有人会问了,为啥不用uex呢?首先我要声明的是Vuex可以实现组件传值,但是当组件多层嵌套时传值会变得很麻烦和繁琐,从最底层的子组件传值至最上层的父组件(或者反过来)可能会跨越好几层组件。
2、EventBus
EventBus 是中央事件总线,父子组件,兄弟组件,爷孙级组件等都可以利用其完成数据传递,也叫全局事件,我们在项目中经常会用得到的,千万不要局限于兄弟组件之间,切记!!!
// eventBus.js
import Vue from 'vue';
export default new Vue;
<template>
<div>
<Item></Item>
<Brother></Brother>
</div>
</template>
<script>
import Item from './components/Son.vue';
import Brother from './components/Brother.vue';
export default {
components: {Item, Brother},
};
</script>
// brother组件
<template>
<div>
<h3>{{message}}</h3>
</div>
</template>
<script>
import bus from '@/utils/eventBus.js';
export default {
name: 'Brother',
data () {
return {
message: '这是兄弟组件的message值'
};
},
mounted () {
bus.$on('update', (res) => {
this.message = res;
});
},
};
</script>
// son组件
<template>
<div>
<el-button type="primary" @click="handleClick">修改</el-button>
</div>
</template>
<script>
import bus from '@/utils/eventBus.js';
export default {
methods: {
handleClick () {
bus.$emit('update', '我是son组件修改Brother的message值');
}
}
};
</script>
3、$attrs / $listeners(多层嵌套组件传递数据或者方法)
// parent组件
<template>
<div>
// 注意:不仅可以向后代组件传递数据,还可以传递方法
<Item :message="msg" :click-function="clickFunction"></Item>
</div>
</template>
<script>
import Item from './components/Son.vue';
export default {
components: {Item},
data () {
return {
msg: 'parent组件的数据'
};
},
methods: {
clickFunction () {
return '返回个啥呢';
},
}
};
</script>
// 子组件
<template>
<div>
// $props监听数据,$listeners监听方法
<Child v-bind="$props" v-on="$listeners" />
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {Child},
// 注意:这里的props声明什么,就可以传递给后代组件什么
props: {
message: {
type: String,
default: ''
},
clickFunction: {
type: Function,
default: () => {}
}
}
};
</script>
// 孙子组件
<template>
<div>
{{message}}
<el-button @click="handleClick">点击</el-button>
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
default: ''
},
clickFunction: {
type: Function,
default: () => {}
}
},
methods: {
handleClick () {
let res = this.clickFunction();
console.log(res);
}
}
};
</script>
4、provide / inject
provide/inject 是依赖注入,需要一起使用,可以让我们指定想要提供给后代组件的数据或方法。不论组件嵌套有多深,允许一个祖先组件向其所有子孙后代注入一个依赖,并在起上下游关系成立的时间里始终生效。
// parent组件
<template>
<div>
<Item></Item>
</div>
</template>
<script>
import Item from './components/Son.vue';
export default {
components: {Item},
data () {
return {
msg: 'parent组件的数据'
};
},
provide () {
return {
name: this.msg,
queryData: this.queryData()
};
},
methods: {
queryData () {
return {
name: '尼玛',
age: 29,
money: '$100'
};
},
}
};
</script>
// 子组件
<template>
<div>
<Child />
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {Child},
};
</script>
// 孙子组件
<template>
<div>
{{name}}
<el-button @click="handleClick">点击</el-button>
</div>
</template>
<script>
export default {
inject: ['name', 'queryData'],
methods: {
handleClick () {
let res = this.queryData;
console.log(res);
}
}
};
</script>
以上就是项目中组件通信常用的几种方式,你学会了吗