categories:
vue 基础
tags:
组件通信
父子组件通信
父子组件, 嵌套一层二层
props 和 $emit
父组件向子组件传递数据是通过 prop 传递的, 子组件传递数据给父组件是通过 $emit 触发事件来做到的
在下面的例子中, 有父组件 App 和子组件 Child
1). 父组件传递了 message 数据给子组件, 并且通过 v-on 绑定了一个 getChildData 事件来监听子组件的触发事件
2). 子组件通过 props 得到相关的 message 数据, 最后通过 this.$emit 触发 getChildData 事件
多级组件通信
$attrs 和 $listeners
第一种方式处理父子组件之间的数据传输有一个问题: 如果父组件 A 下面有子组件 B, 组件 B 下面有组件 C, 这时如果组件 A 和组件 C 通信怎么办?
如果采用第一种方法, 我们必须让组件 A 和组件 B 通过 props 传递消息, 组件 B 再通过 props 和组件 C 通信; 如果组件 A 和组件 C 之间有更多的组件, 那么这种方式过于复杂了. Vue 从 2.4 开始提供了 $attrs 和 $listeners 来解决这个问题, 能够让组件 A 和组件 C 直接通信
- <!doctype html>
- <HTML lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>
- $attrs 和 $listeners
- </title>
- </head>
- <body>
- <div id="app">
- <App>
- </App>
- </div>
- <script src="./vue.js">
- </script>
- <script>
- Vue.component("C", {
- data() {
- return {}
- },
- template: ` < div > <div@click = "cClickHandler" > {
- {
- $attrs.messagec
- }
- } < /div>
- </div > `,
- methods: {
- cClickHandler() {
- this.$emit('getCData', '我是 C 数据')
- }
- }
- }),
- Vue.component("B", {
- data() {
- return {}
- },
- template: ` < div > <C v - bind = "$attrs"v - on = "$listeners" > </C>
- </div > `,
- methods: {}
- }),
- Vue.component("A", {
- data() {
- return {}
- },
- props: ['message'],
- template: ` < div > <B v - bind = "$attrs"v - on = "$listeners" > </B>
- </div > `,
- methods: {}
- });
- var App = {
- data() {
- return {
- msg: '我是父组件',
- messagec: "helloc"
- }
- },
- template: ` < div > <p > 这是一个父组件 < /p>
- <A :messagec="messagec" v-on:getCData="getCData"></A > </div>
- `,
- methods:{
- / / 执行C组件的触发函数getCData(val) {
- console.log(val)
- }
- }
- };
- new Vue({
- el: '#app',
- data() {
- return {}
- },
- components: {
- App
- },
- template: ` < div > <App > </App>
- </div > `
- })
- </script>
- </body>
- </HTML>
中央事件总线
上面两种方式处理的都是父子组件之间的数据传递, 而如果两个组件不是父子关系呢? 这种情况下可以使用中央事件总线的方式. 新建一个 Vue 事件 bus 对象, 然后通过 bus.$emit 触发事件, bus.$on 监听触发的事件
- <!doctype HTML>
- <HTML lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>
- $attrs 和 $listeners
- </title>
- </head>
- <body>
- <div id="app">
- <App>
- </App>
- </div>
- <script src="./vue.js">
- </script>
- <script>
- // 中央事件总线
- var bus = new Vue();
- Vue.component('brother2', {
- data() {
- return {
- msg: "hello brother1"
- }
- },
- template: ` < div > <p > 我是老大 < /p>
- <input type="text" v-model="msg" @input="passData(msg)">
- </div > `,
- methods: {
- passData(val) {
- // 触发全局事件 globalEvent
- bus.$emit('globalEvent', val)
- }
- }
- });
- Vue.component('brother1', {
- data() {
- return {
- msg: "hello brother2",
- brother2Msg: ''
- }
- },
- template: ` < div > <p > 我是老二 < /p>
- <p > 老大传递过来的数据:{{brother2Msg}}</p > </div>
- `,
- mounted(){
- / / 绑定全局事件globalEvent事件bus.$on('globalEvent', (val) = >{
- this.brother2Msg = val;
- })
- }
- });
- var App = {
- data() {
- return {
- msg: '我是父组件对象内容',
- messagec: "hello c"
- }
- },
- methods: {},
- template: ` < div > <brother1 > </brother1>
- <brother2></brother2 > </div>
- `,
- methods:{
- / / 执行c组件的触发的函数getCData(val) {
- console.log(val)
- }
- }
- };new Vue({
- el: '#app',
- data() {
- return {}
- },
- components: {
- App
- },
- template: ` < App > </App>
- `
- })
- /
- </script>
- </body>
- </HTML>
来源: http://www.bubuko.com/infodetail-3383746.html