Vue组件之间数据通信

父组件向子组件传递数据 props

父组件:

<template>
  <div class="container">
    <Child :msg="msgTxt"/>
  </div>
</template>
<script>
import Child from './child.vue';
export default {
    // 注册
  components: {
    Child
  },
  data() {
    return {
      msgTxt: "父组件文字:英雄联盟"
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
  },
}
</script>
<style scoped>
.container{
  background: #fff;
}
</style>

子组件

<template>
  <div>
    <p class="txt">{{msg}}</p>
  </div>
</template>
<script>
export default {
    // 父组件传过来的值
  props: ['msg'],
  data() {
    return {
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
  },
}
</script>
<style scoped>
.txt{
  font-size: 16px;
}
</style>

子组件向父组件传递数据($emit的用法)

父组件

<template>
  <div class="container">
    <Child :list="txtArr" @emitTxt="emitTxt"/>
    <div class="select">选中的游戏名称:{{selectTxt}}</div>
  </div>
</template>
<script>
import Child from './child.vue';
export default {
  components: {
    Child
  },
  data() {
    return {
      txtArr: ['王者荣耀', '英雄联盟', '真三无双'],
      selectTxt: ''
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
    emitTxt(txt) {
      this.selectTxt = txt;
    }
  },
}
</script>
<style scoped>
.container{
  background: #fff;
}
.select{
  margin-top: 20px;
  color: #000;
  font-weight: 600;
}
</style>

子组件

<template>
  <div>
    <p class="txt" v-for="(item, index) in list" :key="index" @click="emitClick(item)">{{item}}</p>
  </div>
</template>
<script>
export default {
  props: ['list'],
  data() {
    return {
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
    emitClick(item) {
      this.$emit('emitTxt', item);
    }
  },
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

兄弟组件之间的通信

A组件 B组件

  • A组件数据传递给共同的父组件 再有父组件接受后传递给B组件

  • 另一种就是使用EventBus(事件总线),它允许两个子组件之间直接通讯,而不需要涉及父组件

方法1需要采用子传父相同,就不再赘言

方法2:

main.js

// mian.js
 
import Vue from 'vue'
import App from './App'
import router from './router'
 
Vue.prototype.$bus = new Vue(); // 设置 挂载至 vue 的原型上
 
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

父组件:

<template>
  <div class="container">
    <Child1 :list="txtArr"/>
    <Child2 />
  </div>
</template>
<script>
import Child1 from './child1.vue';
import Child2 from './child2.vue';
export default {
  components: {
    Child1,
    Child2
  },
  data() {
    return {
      txtArr: ['王者荣耀', '英雄联盟', '真三无双'],
    }
  },
}
</script>
<style scoped>
.container{
  background: #fff;
}
.select{
  margin-top: 20px;
  color: #000;
  font-weight: 600;
}
</style>

子组件1:

<template>
  <div>
    <p class="txt" v-for="(item, index) in list" :key="index" @click="txtClick(item)">{{item}}</p>
  </div>
</template>
<script>
export default {
  props: ['list'],
  data() {
    return {
    }
  },
  methods:{
    txtClick(item) {
      this.$bus.$emit('nameUpdate', item);
    }
  },
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

子组件2:

<template>
  <div>
    <p class="txt">兄弟组件传来的游戏名称:{{gameTitle}}</p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      gameTitle: ''
    }
  },
  mounted() {
    this.$bus.$on('nameUpdate', (value)=>{
      this.gameTitle = value;
    })
  }
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

eventBus事件总线($emit / $on)

兄弟组件已经展示$emit / $on的使用。在此就不在赘言。

通过 ref ,$refs实现通信(父、子组件)

父组件:

<template>
  <div class="container">
    <Child1 :list="txtArr" ref="child"/>
     <el-button type="primary" @click="getGameName">获取子组件选中的游戏名称</el-button>
     <p class="select">{{gameTitle}}</p>
  </div>
</template>
<script>
import Child1 from './child1.vue';
export default {
  components: {
    Child1,
  },
  data() {
    return {
      txtArr: ['王者荣耀', '英雄联盟', '真三无双'],
      gameTitle: ''
    }
  },
  methods:{
    getGameName() {
      this.gameTitle = this.$refs.child.gameTitle;
    }
  },
}
</script>
<style scoped>
.container{
  background: #fff;
}
.select{
  margin-top: 20px;
  color: #000;
  font-weight: 600;
}
</style>

子组件:

<template>
  <div>
    <p class="txt" v-for="(item, index) in list" :key="index" @click="txtClick(item)">{{item}}</p>
  </div>
</template>
<script>
export default {
  props: ['list'],
  data() {
    return {
      gameTitle: ''
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
    txtClick(item) {
      this.gameTitle = item;
    },
  },
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

通过 this.$parent 调用 父组件方法/参数

父组件:

<template>
  <div class="container">
    <div>我是父组件</div>
    <p class="select">{{ name }}</p>
    <Child1/>
  </div>
</template>
<script>
import Child1 from './child1.vue';
export default {
  components: {
    Child1,
  },
  data() {
    return {
      name: ''
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
    getParentName(name) {
      this.name = name;
      console.log("父组件方法getParentName被调用:",name);
    }
  },
}
</script>
<style scoped>
.container{
  background: #fff;
}
.select{
  margin-top: 20px;
  color: #000;
  font-weight: 600;
}
</style>

子组件:

<template>
  <div>
    <p class="txt">我是子组件</p>
    <el-input v-model="value" placeholder="请输入内容" @change="nameChange"></el-input>
    <el-button type="primary" @click="txtClick">调用父组件事件</el-button>
  </div>
</template>
<script>
export default {
  props: ['list'],
  data() {
    return {
      value: ''
    }
  },
  created(){
  },
  computed:{
  },
  methods:{
    txtClick() {
      this.$parent.getParentName(this.value);
    },
    nameChange(value) {
      this.value = value;
    }
  },
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

provide和inject 实现通信

成对出现:provide和inject是成对出现的

作用:用于父组件向子孙组件传递数据

使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问父组件的数据

provider/inject:简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量,需要注意的是这里不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据。

父组件:

<template>
  <div class="container">
    <div>我是父组件</div>
    <Child1/>
    <el-button type="primary" @click="changeValue">主要按钮</el-button>
  </div>
</template>
<script>
import Child1 from './child1.vue';
export default {
  components: {
    Child1,
  },
  data() {
    return {
      parentValue: '我是父组件的值啊'
    }
  },
  provide() {
    return {
      parentValue: this.parentValue
    }
  },
  methods: {
    changeValue() {
      this.parentValue = '修改父组件值';
      this.$nextTick(()=>{
        console.log("修改的值:",this.parentValue);
      });
    }
  }
}
</script>
<style scoped>
.container{
  background: #fff;
}
.select{
  margin-top: 20px;
  color: #000;
  font-weight: 600;
}
</style>

子组件:

<template>
  <div>
    <p class="txt">我是子组件</p>
    <p class="txt">{{parentValue}}</p>
    <Grandson />
  </div>
</template>
<script>
import Grandson from './grandson.vue';
export default {
  components: {
    Grandson,
  },
  // inject:["parentValue"], // 使用一个注入的值作为数据入口:
  inject: {
    // 使用一个默认值使其变成可选项
    parentValue: { // 健名
      from: 'parentValue', // 来源
      default: 'parentValue' // 默认值
    }
  }
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

更深层的组件:

<template>
  <div>
    <p class="txt">我是孙子组件</p>
    <p class="txt">{{parentValue}}</p>
  </div>
</template>
<script>
export default {
  // inject:["parentValue"], // 使用一个注入的值作为数据入口:
  inject: {
    // 使用一个默认值使其变成可选项
    parentValue: { // 健名
      from: 'parentValue', // 来源
      default: 'parentValue' // 默认值
    }
  }
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

从父组件日志可以看到,此时的parentValue不是响应式的值。

修改为响应式provide提供一个函数:

父组件修改为:

<template>
  <div class="container">
    <div>我是父组件</div>
    <Child1/>
    <el-button type="primary" @click="changeValue">主要按钮</el-button>
  </div>
</template>
<script>
import Child1 from './child1.vue';
export default {
  components: {
    Child1,
  },
  data() {
    return {
      parentValue: 1
    }
  },
  provide() {
    return {
      getParentValue: () => ({
        value: this.parentValue
      }),
    };
  },
  methods: {
    changeValue() {
      this.parentValue = this.parentValue + 1;
    }
  }
}
</script>
<style scoped>
.container{
  background: #fff;
}
.select{
  margin-top: 20px;
  color: #000;
  font-weight: 600;
}
</style>

子组件修改为:

<template>
  <div>
    <p class="txt">我是子组件</p>
    <p class="txt">{{parentValue}}</p>
  </div>
</template>
<script>
export default {
  inject:["getParentValue"],
  data() {
    return{
      parentValue: ''
    }
  },
  computed: {
    actParantValue() {
      return this.getParentValue()
    }
  },
  watch: {
    actParantValue(val) {
      this.parentValue = val.value
    }
  }
}
</script>
<style scoped>
.txt{
  font-size: 16px;
  margin-bottom: 10px;
  cursor: pointer;
}
</style>

如果有助你们,麻烦点赞,转发,收藏

谢谢

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值