兄弟组件间通讯总线机制 以及$attrs和$listeners的使用

本文探讨了在Vue中组件间通信的多种方式,包括使用Vuex、中间件组件、自定义事件以及Vue的$attrs和$listeners属性。当组件通信需求不复杂时,使用$attrs和$listeners能简化代码,提高可读性。文章通过实例展示了如何利用这两个属性实现跨级组件的数据传递,并解释了它们与Vue总线机制的对比和适用场景。
摘要由CSDN通过智能技术生成

总线机制

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	
</head>
<body>
	<div id="root">
       <child content="DELL"></child>
	   <child content="LEE"></child>
	</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script type="text/javascript">
	Vue.prototype.bus = new Vue()
   Vue.component('child',{
	 data(){
		return {
			dcontent:this.content
		}  
	  },
	props:{
		content:String
	},
	template:'<div @click="handelClick">{{dcontent}}</div>',
	methods:{
		handelClick(){
			this.bus.$emit('change',this.dcontent)
		}
	},
	mounted(){
		var that = this;
		this.bus.$on('change',function(msg){
			console.log(that);
			that.dcontent=msg
		})
	}
})
  var vm = new Vue({
  	el : '#root',
	data(){
		return{
			msg:"111"
		}
		
	},
	
  })

</script>
</html>

$attrs和$listeners的使用

现在我们来讨论一种情况,A组件与C组件怎么通信,我们有多少种解决方案?

  1. 我们使用VueX来进行数据管理,但是如果项目中多个组件共享状态比较少,项目比较小,并且全局状态比较少,那使用VueX来实现该功能,并没有发挥出VueX的威力。
  2. 使用B来做中转站,当A组件需要把信息传给C组件时,B接受A组件的信息,然后利用属性传给C组件,这是一种解决方案,但是如果嵌套的组件过多,会导致代码繁琐,代码维护比较困难;如果C中状态的改变需要传递给A, 使用事件系统一级级往上传递 。
  3. 自定义一个Vue 中央数据总线,这个情况适合碰到组件跨级传递消息,但是使用VueX感觉又有点浪费的项目中,但是缺点是,碰到多人合作时,代码的维护性较低,代码可读性低

    在很多开发情况下,我们只是想把A组件的信息传递给C组件,如果使用props 绑定来进行信息的传递,虽然能够实现,但是代码并不美观。

    vue2.4中,为了解决该需求,引入了$attrs 和$listeners , 新增了inheritAttrs 选项。 在版本2.4以前,默认情况下父作用域的不被认作props的属性属性百年孤独,将会“回退”且作为普通的HTML特性应用在子组件的根元素上。如下列的例子

    父组件demo代码如下

    <template>
       <div>
         <child-dom
          :foo="foo"
          :coo="coo"
         >
         </child-dom>
       </div>
    </template>
    <script>
       import childDom from "./ChildDom.vue";
       export default {
         data() {
            return {
              foo:"Hello, world",
              coo:"Hello,rui"
            }
         },
         components:{childDom},
       }
    </script>

    子组件child-dom代码如下

    <template>
       <div>
          <p>foo:{{foo}}</p>
       </div>
    </template>
    <script>
    export default {
     name:'child-dom',
     props:["foo"]
    }
    </script>

    当显示父组件时,查看Dom结构,结构如下

    在2.4中新增选项inheritAttrs  inheritAttrs的默认值为true, 将inheritAttrs的值设为false, 这些默认的行为会禁止掉。但是通过实例属性$attrs ,可以将这些特性生效,且可以通过v-bind 绑定到子组件的非根元素上。

    修改子组件代码如下

    <template>
    	<div>
    		<p>foo:{{foo}}</p>
    		<p>attrs:{{$attrs}}</p>
    		<childDomChild v-bind="$attrs"></childDomChild>
    	</div>
    </template>
    <script>
    	import childDomChild from './childDomChild';
    	export default {
    		name: 'child-dom',
    		props: ["foo"],
    		inheritAttrs:false,
    		components: {
    			childDomChild
    		}
    	}
    </script>
    

    新增子组件 childDomChild

    <template>
      <div>
       <p>coo:{{coo}}</p>
      </div>
    </template>
    <script>
      export default {
        name:'childDomChild',
        props:["coo"],
        inheritAttrs:false
      }
    </script>

  4. 从上面的代码,可以看出使用$attrs ,inheritAttrs 属性 能够使用简洁的代码,将A组件的数据传递给C组件 ,该场景的使用范围还是挺广的。

    此时我们又想到了一个问题,c组件的信息,怎么同步给a组件呢? 

    vue2.4版本新增了$listeners 属性,我们在b组件上 绑定 v-on=”$listeners”, 在a组件中,监听c组件触发的事件。就能把c组件发出的数据,传递给a组件。

    A组件代码更新如下


    <template>
     <div>
       <child-dom
        :foo="foo"
        :coo="coo"
         v-on:upRocket="reciveRocket"
       >
       </child-dom>
     </div>
    </template>
    <script>
     import childDom from "@/components/ChildDom.vue";
     export default {
       name:'demoNo',
       data() {
         return {
           foo:"Hello, world",
            coo:"Hello,rui"
        }
      },
     components:{childDom},
     methods:{
       reciveRocket(){
          console.log("reciveRocket success")
       }
     }
    }
    </script>

    b组件更新如下

    <template>
     <div>
     <p>foo:{{foo}}</p>
     <p>attrs:{{$attrs}}</p>
     <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild>
     </div>
    </template>
    <script>
    import childDomChild from './childDomChild';
    export default {
     name:'child-dom'
     props:["foo"],
     inheritAttrs:false,
    }
    </script>

    c组件更新如下

    <template> 
     <div>
     <p>coo:{{coo}}</p>
     <button @click="startUpRocket">我要发射火箭</button>
     </div>
    </template>
    <script>
     export default {
     name:'childDomChild',
     props:['coo'],
     methods:{
     startUpRocket(){
     this.$emit("upRocket");
     console.log("startUpRocket")
     }
     }
     }
    </script>

 现在我们应该清楚了$attrs,$listernersinheritAttrs 的作用了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值