最近在面试一些前端,每当我问起父子组件,兄弟组件之间怎么传值的时候,都回答的支支吾吾,要么回答的支支吾吾,要么回答的不是很全面,在现今前端组件式开发的热潮中,这些是多么的重要,所以今天抽空整理一下,希望给他们一些帮助。
- props 和 $emit(普遍)
- $attrs 和 $listeners(父-子-孙)
- provide 和 inject(父组件向下传递)
- $parent 和 $children(父子组件数据操作)
- eventBus (兄弟组件)
- vuex (状态管理器)
1、props 和 $emit
父组件A向子组件B通过prop传递数据,子组件B通过$emit触发事件传递数据给父组件A
Vue.component('A',{
template:`
<div>
<p>this is parent compoent!</p>
<B :message="message" @getB="getB"></B>
</div>
`,
data(){
return {
messageA:'hello A'
}
},
methods:{
//子组件事件
getChild(val){
console.log(val)
}
}
})
Vue.component('B',{
data(){
return {
messageB:this.messageA
}
},
template:`
<div><input type="text" v-model="messageB" @input="setData(messageB)"></div>
`,
props:['messageA'], //父组件传递过来的数据
methods:{
setData(val){
//传递给父组件
this.$emit('getB',val)
}
}
})
2、$attrs 和 $listeners
父组件A到孙组件C传递数据的时候在用上面的方法,父A传子B,子B传孙C,这样传递虽然也能实现,但是太过于繁琐,所于就出现了$attrs 和 $listeners之间让父组件A把消息传递给孙组件C
Vue.component('A',{
template:`
<div>
<p>this is parent compoent!</p>
<B :messageC="messageC" :messageA="messageA" @getC="getC" @getB="getB(messageA)"></B>
</div>
`,
data(){
return {
messageA:'hello A',
messageC:'hello C' //传递给C组件
}
},
methods:{
getB(val){
console.log('B组件的数据')
},
//触发C组件的事件
getC(val){
console.log("C组件的数据:"+val)
}
}
})
Vue.component('B',{
data(){
return {
messageB:this.messageA
}
},
template:`
<div>
<input type="text" v-model="messageB" @input="setData(messageB)">
<C v-bind="$attrs" v-on="$listeners"></C>
</div>
`,
props:['messageA'],//父组件A传递过来的数据
methods:{
setData(val){
//触发父组件A的事件
this.$emit('getB',val)
}
}
})
Vue.component('C',{
template:`
<div><input type="text" v-model="$attrs.messageC" @input="setCData($attrs.messageC)"></div>
`,
methods:{
setCData(val){
//触发父组件A中的事件
this.$emit('getC',val)
}
}
})
3、provide 和 inject
provide 和 inject,他们成对出现,不管子组件有多少级,用于父级组件向下传递数据。在父组件A中通过provider来设置变量,在子组件B中通过inject来引入变量。
Vue.component('A',{
template:`
<div>
<p>this is parent compoent!</p>
<B></B>
</div>
`,
provide:{
name:'my is parent compoent'
},
data(){
return {
message:'helloA'
}
}
})
Vue.component('B',{
inject:['name'],//获取父组件A传递过来的数据
data(){
return {
messageB:this.name
}
},
template:`
<div>
<input type="tet" v-model="messageB">
</div>
})
4、$parent 和 $children
在父子组件中可以通过$parent 和 c h i l d r e n 进 行 数 据 交 互 , 父 组 件 A 可 以 通 过 children进行数据交互,父组件A可以通过 children进行数据交互,父组件A可以通过children对子组件B进行操作,子组件B可以通过$parent对父组件A进行操作。
Vue.component('A',{
template:`
<div>
<p>this is parent compoent!</p>
<button @click="changeA">确定</button >
<B></B>
</div>
`,
methods:{
changeA(){
this.$children[0].messageB = this.messageA;//改变子组件B的值
}
},
data(){
return {
messageA:'hello A'
}
}
})
Vue.component('B',{
data(){
return {
messageB:'hello B'
}
},
methods:{
changeB(){
this.$parent.messageA = this.messageB;//改变父组件A的值
}
},
template:`
<div>
<input type="text" v-model="messageB" @change="changeB">
</div>
})
var app = new Vue({
el:'#app',
template:`<div><A></A></div>`
})
5、eventBus
如果不是父子组件,是兄弟组件可以用eventBus进行操作,可以创建一个单独的js文件eventVue.js,内容如下:
import Vue from 'vue'
export default new Vue
也可以新建一个vue事件eventBus对象,然后通过eventBus. e m i t 触 发 事 件 , e v e n t B u s . emit触发事件,eventBus. emit触发事件,eventBus.on监听触发的事件
var eventBus = new Vue();
第一种
Vue.component('A',{
template:`
<div>
<B></B>
<C></C>
</div>
`
})
Vue.component('B',{
import eventVue from '../../js/eventVue.js'
data(){
return {
messageB:'hello B'
}
},
methods:{
submit(){
eventVue.$emit("myFun",this.msg) //$emit这个方法会触发一个事件
}
},
template:`
<div>
<button @click="submit">确定</button>
</div>`
})
Vue.component('C',{
import eventVue from '../../js/eventVue.js'
data(){
return {
messageC:'hello C'
}
},
created(){
eventVue.$on("myFun",(message)=>{ //这里最好用箭头函数,不然this指向有问题
this.messageC= message
})
},
template:`
<div>
<div>{{messageC}}</div>
</div>`
})
var app = new Vue({
el:'#app',
template:`<div><A></A></div>`
})
第二种
Vue.component('A',{
data(){
return {
messageA:'hello A'
}
},
methods:{
submit(){
eventVue.$emit("myFun",this.msg) //$emit这个方法会触发一个事件
}
},
template:`
<div>
<button @click="submit">确定</button>
</div>`
})
Vue.component('B',{
data(){
return {
messageB:'hello B'
}
},
created(){
eventVue.$on("myFun",(message)=>{ //这里最好用箭头函数,不然this指向有问题
this.messageB= message
})
},
template:`
<div>
<div>{{messageB}}</div>
</div>`
})
var eventBus = new Vue();
var app = new Vue({
el:'#app',
template:`<div>
<A></A>
<B></B>
</div>`
})
6、vuex
业务逻辑复杂的,组件间需要处理一些公共的数据的可以选择vuex,在这里就不多说了,相信大家学习vue的都了解vuex.