Vue 组件间通信常用的五种方式

目录

1.props和$emit

2.全局事件总线

3.v-model

4.$parent和$children

5.vuex


1.props和$emit

   主要用于父子组件间通信,父组件向子组件传递数据是通过props传递的,子组件向父组件传递数据是通过$emit触发事件做到的

1)父组件向子组件传递数据(子组件通过props接收):

下面通过一个例子进行说明:

<!-- 父组件 -->
<template>
  <div>
    <Children1 :bookList="bookList"></Children1>
    <Children2 :goods="goodList"></Children2>
  </div>
</template>

<script>
import Children1 from './Children1.vue'
import Children2 from './Children2.vue'
export default {
  name: 'Father',
  components: { Children1, Children2 },
  data () {
    return {
      bookList: ['重生', '红楼梦', '三国演义'],
      goodList: ['雪花酥', '冰激淋', '草莓蛋糕']
    }
  }
}
</script>

<style>

</style>
<!-- 子组件 -->
<template>
  <div>
     <ul>
      <li v-for="item in goods" :key="item.index">{{item}}</li>
     </ul>
  </div>
</template>

<script>
export default {
  name: 'Children2',
  props: ['goods']//接受父组件传过来的goods,并进行遍历
}
</script>

<style>

</style>

说明:

    在上面例子中,父组件需要先给需要传递数据的子组件绑定一个属性,属性值就是要传的数据,并且要在父组件中引入子组件。子组件通过props属性接收父组件传过来的值

2)子组件向父组件传递数据

$emit绑定一个自定义事件, 当这个语句被执行时, 就会将参数传递给父组件,父组件通过v-on监听并接收参数。

下面通过一个例子进行说明:

<!-- 父组件 -->
<template>
  <div>
    <Children1 :bookList="bookList" @message="message"></Children1>
    <Children2 :goods="goodList"></Children2>
  </div>
</template>

<script>
import Children1 from './Children1.vue'
import Children2 from './Children2.vue'
export default {
  name: 'Father',
  components: { Children1, Children2 },
  data () {
    return {
      message1: '',
      bookList: ['重生', '红楼梦', '三国演义'],
      goodList: ['雪花酥', '冰激淋', '草莓蛋糕']
    }
  },
  methods: {
    message (recieveMessage) { // 获取子组件传来的数据
      console.log('recieveMessage', recieveMessage)
    }
  }
}
</script>

<style>

</style>
<template>
  <div>
     <div v-for="item in bookList" :key="item.index">
       {{item}}
     </div>
     <Button @click="handleClick">发送数据</Button>
  </div>
</template>

<script>
export default {
  name: 'Children1',
  props: ['bookList'],
  methods: {
    handleClick () {
      this.$emit('message', '冰冰')// 向父组件发射数据obj
    }
  }
}
</script>

<style>

</style>

 说明:

    在上面例子中,子组件通过$emit绑定一个自定义事件,并携带需要传递给父组件的数据,父组件通过v-on绑定该事件来监听子组件的触发事件

2.全局事件总线

本质上是自定义事件,只不过是给$bus绑定的事件,当然当前的$bus就是vm.

是一种组件间通信的方式,适用于任意组件间通信

1.安装全局事件总线

 首先在main.js里面注册全局事件总线

new Vue({
    el: '#app',
    router,
    i18n,
    store,
    //安装全局事件总线
   beforeCreate()
    {
      Vue.prototype.$bus=this
    },
    render: h => h(App)
})

2.使用全局事件总线

1)接收数据,通过this.$bus.$on('事件名称',回调)

 created () {
    // 接收数据
    // 或直接使用回调函数,切记是箭头函数,不然this不是当前组件
    this.$bus.$on('data', (msg) => {
      console.log('收到了数据', msg)
      this.info = msg
    })
  }

2)提供数据,this.$bus.$emit('xxxx',数据)

3)最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件 

实例代码:

busPage.vue(提供数据):

<template>
  <div>Bus 提供数据 <Button type="primary" @click="givemessage">提供数据</Button></div>
</template>

<script>
export default {
  name: 'busPage',
  data () {
    return {
      info: {
        name: '王俊凯',
        age: 23
      }
    }
  },
  methods: {
    givemessage () {
      // 调用事件,发送数据
      this.$bus.$emit('data', this.info)
      console.log('发送了数据', this.info)
    }
  }
}
</script>

<style>

</style>

dataAnalysis.vue(接收数据):

<template>
  <div>
    接收到的数据: {{this.info}}
  </div>
</template>

<script>
export default {
  name: 'dataAnalysis',
  data () {
    return {
      info: {}
    }
  },
  created () {
    // 接收数据
    // 或直接使用回调函数,切记是箭头函数,不然this不是当前组件
    this.$bus.$on('data', (msg) => {
      console.log('收到了数据', msg)
      this.info = msg
    })
  },
  beforeDestroy () {
    // 组件即将销毁时,解绑事件
    this.$bus.$off('data')
  }
}
</script>

<style>

</style>

3.v-model

   为了实现数据的双向传递,即在父组件中更新,子组件会立即更新;在子组件中修改了值,父组件也会立即更新,此时v-model就可以实现这种需求,使用v-model的过程中,父组件我们还是需要正常将子组件引入,只是传值的方式变成了v-model

示例说明:

父组件:

<template>
   <data-analysis v-model="fatherText"></data-analysis>
   <p>这里显示的是父组件的fatherText值:{{this.fatherText}}</p>
  </div>

</template>

<script>
import dataAnalysis from '../dataAnalysis/index.vue'
export default {
  name: 'busPage',
  components: {dataAnalysis},
  data () {
    return {
      fatherText: '今天天气真好'
    }
  }
}
</script>

<style>

</style>

子组件:

model默认情况下:

prop: 默认绑定的是value
event: 默认触发的事件类型是input

<template>
  <div >
   <span>这里显示子组件input的value1值</span>
   <input type="text" :value="fatherText" @input="handleInput">
  </div>
</template>

<script>
export default {
  name: 'dataAnalysis',
  model: {
    prop: 'fatherText',
    event: 'handleClick'
  },
  props: {
    fatherText: {
      type: String
    }
  },
  data () {
    return {
    }
  },
  methods: {
    handleInput (e) {
      this.$emit('handleClick', e.target.value)
    }
  }
}
</script>

<style>

</style>

4.$parent和$children

使用 this.$parent查找当前组件的父组件。
使用 this.$children查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的。

使用 this.$root查找根组件,并可以配合$children遍历全部组件。
使用 this.$refs查找命名子组件。

 示例说明:

父组件:

busPage.vue:

<template>
  <div>
{{msg}}
 <data-analysis ref="dataAnalysis"></data-analysis>
 <regional-manage ref="regionalManage"></regional-manage>
  </div>

</template>

<script>
import dataAnalysis from '../dataAnalysis/index.vue'
import regionalManage from '../regionalManage/index.vue'
export default {
  name: 'busPage',
  components: {dataAnalysis, regionalManage},
  data () {
    return {
      msg: '今天天气真好',
      message: 'busPage'
    }
  },
  mounted () {
    console.log(this.$children[0].message)// dataAnalysis(读取子组件时,this.$children子组件的排序是不安全的)
    console.log(this.$refs.regionalManage.message)// regionalManage(读取命名子组件数据)
    console.log(this.$root.$children[0].message)// App组件
    console.log(this.$root.$children[0].$children[0].message)
  },
  methods: {
  }
}
</script>

<style>

</style>

子组件1:

dataAnalysis.vue:

<template>
  <div >
   数据统计分析
   这是读取父组件中的数据:{{msg}}
  </div>
</template>

<script>
// import regionalManage from '../regionalManage/index.vue'
export default {
  name: 'dataAnalysis',
  data () {
    return {
      message: 'dataAnalysis',
      msg: ''
    }
  },
  methods: {

  },
  created () {
    this.msg = this.$parent.message
  },
  beforeDestroy () {

  }
}
</script>

<style>

</style>

 子组件2:

  regionalManage.vue:

<template>
  <div>
    风险地区
  </div>
</template>

<script>
export default {
  name: 'regionalManage',
  data () {
    return {
      message: 'regionalManage'
    }
  }
}
</script>

<style>

</style>

5.vuex

vuex比较重要,在另一篇笔记中单独说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值