Vue组件传值和中央事件总线Bus

在认识Vue中央事件总线之前,先来看看什么是组件传值

一、组件传值

  • 父组件通过属性给子组件传值: 子组件的props接受数据(注意属性传值是单向的)
  • 子组件通过调用父组件的方法给父组件传值:子组件的自定义事件中,用$emit触发事件调用父组件方法给父组件传值

因为通过属性传值是单向的,有时候我们需要子组件的data 数据需要交给父组件使用: 通过在子组件上定义自定义事件,在子组件中通过$emit 来触发事件;子组件的事件被触发并传参,事件处理函数可以接收到子组件的数据;事件绑定的事件处理函数在父节点上,故可在事件处理函数中用到子组件的数据值来修改父节点的数据。

//父组件中:
<my-search @myevent="handleEvent"></my-search>
//myevent是事子组件的自定义事件 
//handleEvent是绑定的父组件的方法


子组件中:
在任意业务中触发事件:this.$emit("myevent","要给父组件传的数据")
  • 多层组件传值:$listeners/$attrs

在不用状态管理vuex的时候,如何让GrandFather与Son通信,我们可以用可以emit一层一层的传递:会显得冗余。 vue2.4之后,提出$attrs、$listeners ,可以实现跨级组件通信。

$listeners官网解说:事件传递

$attrs官网解说:属性传递

在组件中绑定 可以把当前组件的自定义属性和方法传给子元素使用:

one组件:<two v-bind:xx="100" v-on:twoEvent="fn"></two>
two组件中:<three v-bind="$attrs" v-on="$listeners"></three>
three组件:可以访问two的 属性和触发事件: {{this.$attrs.xx}} this.$emit("twoEvent",20)
  • $parent/$root、$children/$refs

这些功能都是有劣势或危险的场景的,官方建议我们尽量避开它们

 $root: 访问根组件vm对象,所有的子组件都可以将这个实例作为一个全局 store 来访问或使用,现在有更好的技术vuex代替。
 
 $parent:访问父组件对象,直接操作父组件的data数据,不需要再使用属性传值,但是容易出现渲染混乱之后只渲染一个的情况
 
 $children:访问子组件对象数组,不能保证顺序,也不是响应式的
          
 $refs:只会在组件渲染完成之后生效,并且它们不是响应式的。你应该避免在模板或计算属性中访问 $refs。
 
 //在组件或者原生元素绑定ref属性(类似于id):
 <myinput ref="myInput1"></myinput>
 <input ref="myInput2"></input>
 
 //在父组件中可以通过 this.$refs访问到它:
 methods: {
   focus: function () {
     this.$refs.myInput2.focus()
   }
 }
 
  • sync修饰符

父组件属性通过.sync修饰,子组件this.$emit("update:绑定属性",修改的值)

//父组件
<template>
	<div>
		<h1>app----{{count}}</h1>
        <Box :n.sync="count"></Box>
	</div>
</template>

<script>
	import Box from "./Box.vue"
	export default {
       data() {
       	return {
       		count: 20
       	}
       },
	   components:{
		   Box
	   }
	}
</script>



//子组件
<template>
	<div>
		<h1>box----{{n}}</h1>
		<button @click="fn">儿子修改爸爸</button>
	</div>
</template>

<script>
	export default {
	  props:["n"],
	  methods:{
		  fn(){
			  this.$emit("update:n",this.n+1)
		  }
	  }
	}
</script>

二、中央事件总线Bus

通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果,全局的eventBus简单理解为在一个文件创建一个新的vue实例然后暴露出去, 使用的时候import这个模块进来即可

第一步:创建一个bus.js文件通过export default导出

//vue-bus.js文件
const install = function (Vue) {
  const Bus = new Vue({
    methods: {
      emit(event, ...args) {
        this.$emit(event, ...args);
      },
      on(event, callback) {
        this.$on(event, callback);
      },
      off(event, callback) {
        this.$off(event, callback);
      }
    }
  });
  Vue.prototype.$bus=Bus;//由于这个新的vm放在与界面绑定的那个vm的原型上,因此页面上的所有组件都能通过this.$bus访问这个新vm对象
};
export default install;

第二步:创建一个main.js文件,使用import导出

//main.js文件
import VueBus from './vue-bus'
Vue.use(VueBus);

//组件文件中:
任意业务中都可以通过调用来绑定事件,触发事件并传值,和销毁事件 
this.$bus.on(event,callback) 
this.$bus.off(event,callback) 
this.$bus.emit(event, ...args)

示例:
组件1:
 this.$bus.on('changedFormObject',(val) =>{
	        //接受并处理传过来的值:val
            this.msg = val;
        });

组件2:
this.$bus.emit('changedFormObject',this.inputValue);//把组件2的data中的给inputValue值传给组件1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 组件传值有以下几种方式: 1. 父组件向子组件传值:通过 props 属性将数据传递给子组件。 ``` //父组件 <template> <div> <Child :name="name"></Child> </div> </template> <script> import Child from "./Child.vue"; export default { name: "Parent", components: { Child }, data() { return { name: "Tom", }; }, }; </script> //子组件 <template> <div>{{ name }}</div> </template> <script> export default { name: "Child", props: { name: String, }, }; </script> ``` 2. 子组件向父组件传值:通过 emit 方法触发父组件的事件传递数据。 ``` //子组件 <template> <div> <button @click="sendData">发送数据</button> </div> </template> <script> export default { name: "Child", data() { return { message: "Hello World", }; }, methods: { sendData() { this.$emit("send", this.message); }, }, }; </script> //父组件 <template> <div> <Child @send="getMessage"></Child> <div>{{ message }}</div> </div> </template> <script> import Child from "./Child.vue"; export default { name: "Parent", components: { Child }, data() { return { message: "", }; }, methods: { getMessage(data) { this.message = data; }, }, }; </script> ``` 3. 兄弟组件之间传值:通过一个中央事件总线 bus 实现。 ``` //bus.js import Vue from 'vue'; export const bus = new Vue(); //兄弟组件1 <template> <div> <button @click="sendData">发送数据</button> </div> </template> <script> import { bus } from './bus.js'; export default { name: "Brother1", data() { return { message: "Hello World", }; }, methods: { sendData() { bus.$emit("send", this.message); }, }, }; </script> //兄弟组件2 <template> <div>{{ message }}</div> </template> <script> import { bus } from './bus.js'; export default { name: "Brother2", data() { return { message: "", }; }, created() { bus.$on("send", (data) => { this.message = data; }); }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值