vue 组件之间的通信 非业务性组件不应该依赖 vuex

注意 1vue 组件之间的通信。(非业务性组件。不应依赖vuex) 。可以 自己管理好自己,也可以借助下面的方式。 

provide/inject

祖先组件中通过provider来提供变量,然后在孙组件中通过inject来注入变量

procide/inject API主要解决了跨域组件间的通讯问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系

下边通过一个例子来说明provide/inject的用法:

  • 父组件
<template>
    <div>
        <son prop="data"></son>
    </div>
</template>
 
<script>
export default {
    provide: {
        name: 'Tom'
    }
}
  • 孙子组件
这里的孙子组件指的是:父组件、子组件、孙子组件
<template>
    <div>
        {{name}}
    </div>
</template>
 
<script>
export default {
    name: 'grandson',
    inject: [name]
}
</script>

这里可以通过inject直接访问其两个层次以上的数据,

用法与props完全相同

 

方法2 使用中间 bus 必须保证 2组件都被渲染了(归根结底是 发布订阅(模式))

这个方法可用于父子、隔代、兄弟组件通信

这种方式是通过一个类似App.vue的实例作为一个模块的事件中心,用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件

当项目比较大的时候,可以选择更好的状态管理解决方案vuex

下边我们来通过一个实例说明emit/on的用法:

在这里先说一下:

有两个组件A、B,在B组件中接收到A组件传过来的数据

首先开辟个新的Vue根实例

然后我们在A组件中通过$emit方式去定义一个自定义事件方法

然后通过$on去接收A组件自定义的事件传过来的值

  • 首先创建一个vue的空白实例
import Vue from 'vue'
export default new Vue()
  • 子组件A
把组件A通过$emit传到那个Vue空白实例里面
<template>
    <div>
        <span>A组件->{{msg}}</span>
        <input type="button" value="把a组件数据传给b" @click ="send">
    </div>
</template>
<script>
import vmson from "util/emptyVue"
export default {
    data(){
        return {
            msg:{
                a:'666',
                b:'999'
            }
        }
    },
    methods:{
        send:function(){
            vmson.$emit("aevent",this.msg)
        }
    }
}
</script>
  • 子组件B
组件B通过$on去监听vmson实例中的自定义方法aevent
<template>
 <div>
    <span>{{msg}}</span>
 </div>
</template>
<script>
      import vmson from "util/emptyVue"
      export default {
         data(){
                return {
                    msg:""
                }
            },
         mounted(){
                vmson.$on("aevent",(val)=>{//监听aevent事件
                    console.log(val);//打印出来结果
                    this.msg = val;
                })
          }
    }
</script>
  • 父组件
这个父组件就是把A、B两个组件放在父组件中注册渲染
<template>
     <div>
      <childa></childa>
      <childb></childb>    
     </div>
</template>
<script>
   import childa from './childa.vue';
   import childb from './childb.vue';
   export default {
    components:{
        childa,
        childb
    },
    data(){
        return {
            msg:""
        }
    },
    methods:{
       
    }
   }
</script>

方法3 如果仅仅是传递(儿子只做一个简单转手,就传递给孙子组件)给孙子组件

attrs/listeners

用在父组件传递数据给子组件或者孙组件
如果仅仅是传递数据,就用$attrs/$listeners好点

如何不仅传递数据,还做中间处理,就用vuex好些

$attrs:

$attrs继承所有的父组件属性(除了prop传递的属性、class和style)

当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。

$listeners:

它是一个对象,包含了父作用域中的v-on事件监听器,可以配合v-on="$listeners"将所有的事件监听器指向这个组件的某个特定的子元素

下面我们来通过一个实例看attrs/attrs/listeners的用法:

例:假设有三个组件:A组件包含B组件,B组件包含C组件

  • A组件
<template>
    <div id="app">
        <child1 :p-child1="child1" :p-child2="child2" v-on:test1="onTest1" 
        v-on:test2="onTest2"
        //此处监听了两个事件,可以在B组件或者C组件中直接触发
        >
        </child1>
    </div>
</template>
<script>
import Child1 from './Child1.vue';
export default {
    data() {
        return {};
    },
    components: { Child1 },
    methods: {
        onTest1() {
            console.log('test1 running...');
        },
        onTest2() {
            console.log('test2 running');
        }
    }
};
</script>
  • B组件
<template>
    <div class="child-1">
        <p>in child1:</p>
        <p>props: {{pChild1}}</p>
        <p>$attrs: {{$attrs}}</p>
        <hr>
        <child2 v-bind="$attrs" v-on="$listeners"></child2>
            //v-on绑定了$listeners,所以C组件能直接触发test
            //v-bind绑定了$attrs,所以C组件可以获取A组件传递下来的props的值
    </div>
</template>
<script>
import Child2 from './Child2.vue';
export default {
    props: ['pChild1'],
    data() {
        return {};
    },
    inheritAttrs: false,
    components: { Child2 },
    mounted() {
        this.$emit('test1');
    }
};
</script>
  • C组件
<template>
    <div class="child-2">
        <p>in child2:</p>
        <p>props: {{pChild2}}</p>
        <p>$attrs: {{$attrs}}</p>
        <hr>
    </div>
</template>
<script>
export default {
    props: ['pChild2'],
    data() {
        return {};
    },
    inheritAttrs: false,
    mounted() {
        this.$emit('test2');
    }
};
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值