Vue组件传值的几种常用方式

引言

Vue的两大特性:响应式组件化。当项目体积和工程量开发到比较大的时候,一个vue文件有几千行代码的时候,这样是不利于开发和维护的,我们经常做的是抽离组件,而谈论组件,不得不考虑组件之间是如何传值的,今天我们就来探讨一下组件之间是如何传递数据的。

1、父组件向子组件通过props传递数据,子组件通过$emit(派发事件的方式)给修改父组件的数据,进而修改子组件数据

// 父组件
<template>
  <div>
    <div >{{title}}</div>
    // 注意 .sync可以帮我们实现父组件向子组件传递的数据的双向绑定
    <Item
      :title.sync="title"
      :pay-type="payType"
      @updateMsg="handleUpdate"
    >
    </Item>
  </div>
</template>
<script>
import Item from './components/Son.vue';
export default {
  components: {Item},
  data () {
    return {
      title: '我是父组件',
      payType: 'tested',
    };
  },
  methods: {
    handleUpdate (val) {
	  this.payType = val;
	}
  }
};
</script>
// 子组件
<template>
  <div>
    <div>{{payType}}</div>
    <el-button @click="handleClick">点我</el-button>
    <el-button @click="handleClick2">再点</el-button>
    <div>{{title}}</div>
  </div>
</template>
<script>
export default {
  props: {
  	title: {
      type: String,
      default: ''
    },
    payType: {
      type: String,
      default: ''
    }
  },
  methods: {
    handleClick () {
      this.$emit('updateMsg', 'testing');
    },
    handleClick2 () {
      // 子组件是可以通过update直接去修改父组件的值的,这里不同于this.$emit触发一个方法通过修改父组件的数据进而修改子组件的数据,这里好好思考一下哦
      this.$emit('update:title', '好像是能改变的');
    }
  }
};
</script>

如果是兄弟组件需要穿插数据呢?
或许有人会问了,为啥不用uex呢?首先我要声明的是Vuex可以实现组件传值,但是当组件多层嵌套时传值会变得很麻烦和繁琐,从最底层的子组件传值至最上层的父组件(或者反过来)可能会跨越好几层组件。

2、EventBus

EventBus 是中央事件总线,父子组件,兄弟组件,爷孙级组件等都可以利用其完成数据传递,也叫全局事件,我们在项目中经常会用得到的,千万不要局限于兄弟组件之间,切记!!!

// eventBus.js
import Vue from 'vue';
export default new Vue;
<template>
  <div>
    <Item></Item>
    <Brother></Brother>
  </div>
</template>
<script>
import Item from './components/Son.vue';
import Brother from './components/Brother.vue';
export default {
  components: {Item, Brother},
};
</script>
// brother组件
<template>
  <div>
    <h3>{{message}}</h3>
  </div>
</template>
<script>
import bus from '@/utils/eventBus.js';
export default {
  name: 'Brother',
  data () {
    return {
      message: '这是兄弟组件的message值'
    };
  },
  mounted () {
    bus.$on('update', (res) => {
      this.message = res;
    });
  },
};
</script>
// son组件
<template>
  <div>
    <el-button type="primary" @click="handleClick">修改</el-button>
  </div>
</template>
<script>
import bus from '@/utils/eventBus.js';
export default {
  methods: {
    handleClick () {
      bus.$emit('update', '我是son组件修改Brother的message值');
    }
  }
};
</script>

3、$attrs / $listeners(多层嵌套组件传递数据或者方法)

// parent组件
<template>
  <div>
    // 注意:不仅可以向后代组件传递数据,还可以传递方法
    <Item :message="msg" :click-function="clickFunction"></Item>
  </div>
</template>
<script>
import Item from './components/Son.vue';
export default {
  components: {Item},
  data () {
    return {
      msg: 'parent组件的数据'
    };
  },
  methods: {
    clickFunction () {
      return '返回个啥呢';
    },
  }
};
</script>
// 子组件
<template>
  <div>
    // $props监听数据,$listeners监听方法
    <Child v-bind="$props" v-on="$listeners" />
  </div>
</template>
<script>
import Child from './Child.vue';
export default {
  components: {Child},
  // 注意:这里的props声明什么,就可以传递给后代组件什么
  props: {
    message: {
      type: String,
      default: ''
    },
    clickFunction: {
      type: Function,
      default: () => {}
    }
  }
};
</script>
// 孙子组件
<template>
  <div>
    {{message}}
    <el-button @click="handleClick">点击</el-button>
  </div>
</template>
<script>

export default {
  props: {
    message: {
      type: String,
      default: ''
    },
    clickFunction: {
      type: Function,
      default: () => {}
    }
  },
  methods: {
    handleClick () {
      let res = this.clickFunction();
      console.log(res);
    }
  }
};
</script>

4、provide / inject

provide/inject 是依赖注入,需要一起使用,可以让我们指定想要提供给后代组件的数据或方法。不论组件嵌套有多深,允许一个祖先组件向其所有子孙后代注入一个依赖,并在起上下游关系成立的时间里始终生效。

// parent组件
<template>
  <div>
    <Item></Item>
  </div>
</template>
<script>
import Item from './components/Son.vue';
export default {
  components: {Item},
  data () {
    return {
      msg: 'parent组件的数据'
    };
  },
  provide () {
    return {
      name: this.msg,
      queryData: this.queryData()
    };
  },
  methods: {
    queryData () {
      return {
        name: '尼玛',
        age: 29,
        money: '$100'
      };
    },
  }
};
</script>
// 子组件
<template>
  <div>
    <Child />
  </div>
</template>
<script>
import Child from './Child.vue';
export default {
  components: {Child},
};
</script>
// 孙子组件
<template>
  <div>
    {{name}}
    <el-button @click="handleClick">点击</el-button>
  </div>
</template>
<script>

export default {
  inject: ['name', 'queryData'],
  methods: {
    handleClick () {
      let res = this.queryData;
      console.log(res);
    }
  }
};
</script>

以上就是项目中组件通信常用的几种方式,你学会了吗

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值