目录

一、父子组件之间的通信方式

1.props+$emit()

3.$parent+$children

4.provide+inject

5.$attrs+$listeners

6.ref+$refs

二、兄弟组件之间的通信方式

1.子传值到父,再由父传值到子

2.事件总线


(备注视频代码学习来自:重要!父子组件通信的方式有哪几种?【Vue面试题】_哔哩哔哩_bilibili

一、父子组件之间的通信方式

1.props+$emit()

1.父组件通过props向子组件传递数据(在子组件中用props接收)

2.子组件通过$emit()向父组件传递数据或事件,如在子组件中自定义事件changeMessage,携带信息'bye’, 然后在父组件中通过v-on监听这个事件

parent.vue

<template>
  <div id="app">
    <h1>父亲</h1>
    <p>{{message}}</p>
    <child :message="message" @changeMessage="message =$event"> </child>
  </div>
</template>

<script>
import Child from "./child.vue"
export default {
  data () {
    return {
      message: 'hello'
    }
  },
  components: {
    Child
  },
  methods: {
    changeMeaasge () {
      this.message = 'Bye'
    }
  }
}
</script>

child.vue

<template>
  <div>
    <h1>孩子</h1>
    <p>{{message}}</p>
    <button @click="handleClick"> 按钮</button>
  </div>
</template>
<script>
export default {
  props: ['message'],
  methods: {
    handleClick () {
      this.$emit('changeMessage', 'Bye')
    }
  }
}
</script>

运行后如下,点击按钮,父亲孩子下面的hello都会变成bye。

                                            

2.通过回调函数(callback)

parent.vue(将changeMsgFn作为另外一个props传给子组件)

<template>
  <div id="app">
    <h1>父亲</h1>
    <p>{{message}}</p>
    <child :message="message" :changeMsgFn="changeMeaasge"> </child>
  </div>
</template>
<script>
import Child from "./child.vue"
export default {
  data () {
    return {
      message: 'hello'
    }
  },
  components: {
    Child
  },
  methods: {
    changeMeaasge () {
      this.message = 'Bye'
    }
  }
}
</script>

 child.vue

<template>
  <div>
    <h1>孩子</h1>
    <p>{{message}}</p>
    <button @click="changeMsgFn"> 按钮</button>
  </div>
</template>
<script>
export default {
  props: ['message', 'changeMsgFn'],
}
</script>

3.$parent+$children

1.父组件通过$children访问子组件

2.子组件通过$parent访问父组件

parent.vue

<template>
  <div id="app">
    <h1>父亲</h1>
    <p>{{message}}</p>
    <button @click="changeChildNumber">按钮</button>
    <child></child>
  </div>
</template>
<script>
import Child from "./child.vue"
export default {
  data () {
    return {
      message: 'hello'
    }
  },
  components: {
    Child
  },
  methods: {
    changeChildNumber () {
      this.$children[0].number = 50
    }
  }
}
</script>

 child.vue

<template>
  <div>
    <h1>孩子</h1>
    <p>{{number}}</p>
    <p>{{parentMessage}}</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      number: 10
    }
  },
  computed: {
    parentMessage () {
      return this.$parent.message
    }
  }
}
</script>

                  (点击按钮后子组件中的数据10变为50)

4.provide+inject

parent.vue

<template>
  <div id="app">
    <h1>父亲</h1>
    <child></child>
  </div>
</template>
<script>
import Child from "./child.vue"
export default {
  components: {
    Child
  },
  provide: {
    message: 'Hello'
  }
}
</script>

 child.vue

<template>
  <div>
    <h1>孩子</h1>
    <p>{{message}}</p>
  </div>
</template>
<script>
export default {
  inject: ['message']
}
</script>

                                                             

5.$attrs+$listeners

parent.vue

<template>
  <div id="app">
    <h1>父亲</h1>
    <p>姓名:{{name}}</p>
    <p>年龄:{{age}}</p>
    <child :name="name" :age="age" @changeName='changeName'></child>
  </div>
</template>
<script>
import Child from "./child.vue"
export default {
  components: {
    Child
  },
  data () {
    return {
      name: 'pipi',
      age: 1
    }
  },
  methods: {
    changeName () {
      this.name = 'wuyi'
    }
  }
}
</script>

child.vue

<template>
  <div>
    <h1>孩子</h1>
    <button @click="$listeners.changeName">按钮</button>
    <grand-child v-bind="$attrs"></grand-child>
  </div>
</template>
<script>
import GrandChild from './GrandChild.vue'
export default {
  components: {
    GrandChild
  }
}
</script>

GrandParent.vue

<template>
  <div>
    <h1>孙子</h1>
    <p>姓名:{{$attrs.name}}</p>
    <p>年龄:{{$attrs.age}}</p>
  </div>
</template>
<script>
export default {
}
</script>

                                                  

6.ref+$refs

parent.vue

<template>
  <div id="app">
    <h1>父亲</h1>
    <child ref="childComp"></child>
    <button @click="changeName">按钮</button>
  </div>
</template>
<script>
import Child from "./child.vue"
export default {
  components: {
    Child
  },
  methods: {
    changeName () {
      console.log('点击前', this.$refs.childComp.age);
      this.$refs.childComp.changeAge();
      console.log('点击后', this.$refs.childComp.age);
    }
  }
}
</script>

  child.vue

<template>
  <div>
    <h1>孩子</h1>
  </div>
</template>
<script>
export default {
  data () {
    return {
      age: 20
    }
  },
  methods: {
    changeAge () {
      this.age = 50;
    }
  }
}
</script>

                                                

每种通信方式还需要继续学习,各自优缺点局限性等....

二、兄弟组件之间的通信方式

1.子传值到父,再由父传值到子

<template>
  <div id="app">
    <h1>父亲</h1>
    <p>name:{{name}}</p>
    <hr>
    <child11 :name="name" @ChildOneClick="handleParentClick" />
    <hr>
    <child22 :name="name" />
  </div>
</template>

<script>
import child11 from './child11.vue'
import child22 from './child22.vue'

export default {
  data () {
    return {
      name: 'pipiwuyi'
    }
  },
  methods: {
    handleParentClick (name) {
      this.name = name;
    }
  },
  components: {
    child11,
    child22,
  },
}
</script>

child11.vue

<template>
  <div>
    <h1>孩子1</h1>
    <p>name:{{name}}</p>
    <button @click="handleChildOneClick">按钮</button>
  </div>
</template>

<script>
import { eventBus } from '../main'
export default {
  props: ['name'],
  methods: {
    handleChildOneClick () {
      this.$emit('ChildOneClick', 'hui')
    }
  }
}
</script>

 child22.vue

<template>
  <div>
    <h1>孩子2</h1>
    <p>name:{{name}}</p>

  </div>
</template>

<script>

export default {
  props: ['name']
}
</script>

                                                           

2.事件总线

new一个新的vue实例并导出,子组件都引入,子组件1$emit出去,子组件2$on监听

main.js

import Vue from 'vue'
import App from './App.vue'

export const eventBus = new Vue(); //创建实例,并导出

Vue.config.productionTip = false

new Vue({
    render: h => h(App),
}).$mount('#app')

parent.vue

<template>
  <div id="app">
    <h1>父亲</h1>
    <p>name:{{name}}</p>
    <hr>
    <Child1 :name="name" @ChildOneClick="handleParentClick" />
    <hr>
    <Child2 :name="name" />
  </div>
</template>

<script>
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'

export default {
  data () {
    return {
      name: 'pipiwuyi'
    }
  },
  methods: {
    handleParentClick (name) {
      this.name = name;
    }
  },
  components: {
    Child1,
    Child2,
  },
}
</script>

child1.vue

<template>
  <div>
    <h1>孩子1</h1>
    <p>name:{{myName}}</p>
    <button @click="handleChildOneClick">按钮</button>
  </div>
</template>

<script>
import { eventBus } from '../main'
export default {
  props: ['name'],
  data () {
    return {
      myName: this.name
    }
  },
  methods: {
    handleChildOneClick () {
      // this.$emit('ChildOneClick', 'hui')
      this.myName = 'hui';
      eventBus.$emit('ChildOneClick', 'hui')//eventBus是vue的实例,存在$emit的方法
    }
  }
}
</script>

child2.vue

<template>
  <div>
    <h1>孩子2</h1>
    <p>name:{{myName}}</p>

  </div>
</template>

<script>
import { eventBus } from '../main'
export default {
  props: ['name'],
  data () {
    return {
      myName: this.name
    }
  },
  created () {
    eventBus.$on('ChildOneClick', (name) => {
      this.myName = name;
    })
  }
}
</script>

点击按钮,两个子组件中的内容改变,父组件中不变 

Logo

前往低代码交流专区

更多推荐