Vue组件间通信的8种方式

1.常用的父子组件通讯方式:props,$emit

父组件传入属性,子组件通过props来接收,在子组件中就可以用this.xxx方式使用。

子组件通过$emit(事件名,参数)向外弹出一个自定义事件,在父组件中的属性监听事件,可以获得子组件中传出来的值

//父组件
<com-view :show="isShow" @onClick="getComView"></com-view>

//子组件
props: {
   isShow:{
    type: Boolean,
       value: false,
  },
}, data() {
return { name: '123123', }; }, methods: { onComView(){ this.$emit('onClick',name); }, }

2.$parent,$children

通过 $parent,$children 来访问组件实例,进而去获取 或者 改变父子组件的值。 (仅限于父子组件之间,不推荐使用,因为不利于维护,一旦组件层次发生了变化,就需要更改其中的层次关系)

需要注意边界,最外层的#app 的$parent得到的是Vue实例,在Vue实例上再去取$parent 就是undefined了。 在最底层的组件中 $children是[]。

以父组件为桥梁去注册事件和触发事件来实现的兄弟组件通讯

//子组件一
this.$parent.$on('confirm',handleConfirm);
//子组件二
this.$parent.$emit('confirm',list);

获取第一个子组件的数据和调用根组件的方法

//获取第一个子组件的数据
console.log(this.$children[0].msg);
//调用根组件的方法
this.$root.handleRoot();

3.$ref

通过引用的方式获取子节点,常用于父组件中调用子组件的方法或者获取子组件的属性。

注意:如果绑在的是v-for的节点上,那么获取到的是一个数组。

//Child.vue
export default {
    data() {
        return {
            name: '123123',
        };
    },
    methods: {
        getComView(val){
            //接收子组件传回的数据信息
           console.log(val);
        },
    }
}

//Parent.vue
<template>
    <div>
        <child ref="child"></child>
    </div>
</template>
<script>
export default {
  mounted(){     const child
= this.$refs.child;     console.log(child.name); //123123     child.getComView('调用了子组件的方法');   }, } </script>

4.provide/inject

依赖注入,常见于插件或者组件库里。

多个组件嵌套时,顶层组件provide提供变量,后代组件都可以通过inject来注入变量。

//顶屋组件
export default {
   provide() {
        return {
            name: '123123',
        };
    },
}

//后代组件
export default {
   inject:['name']
}

缺陷:传递的数据不是响应式的,inject接收到数据后,provide中的数据改变,但是后代组件中的数据不会改变。所以 建议传一些常量或者方法。

//父组件
export default {
  //方法一 不能获取methods中的方法
  provide:{
    name:'123123',
  },
  //方法二 不能获取data中的属性
  provide(){
     return{
      name:'123123',
      someMethod:this.someMethod //methods中的方法
    }
  },
    methods: {
        someMethod(){
           console.log('这是注入的方法')
        },
    }
}

//后代组件
export default {
  inject:['name','someMethod'],
  mounted(){
    console.log(this.name);
    this.someMethod();
  }
}

5.EventBus 事件总线 (任意两个组件通讯)

//方法一
//抽离成一个单独的js文件Bus.js,然后在需要的地方引入
//Bus.js
import Vue from "vue"
export default new Vue()

//方法二 直接挂载到全局
//main.js
import Vue from "vue"
Vue.prototype.$bus = new Vue()

//方法三 注入到Vue根对象上
//main.js
import Vue from "vue"
new Vue({
  el:"#app",
  data:{
    Bus:new Vue()
  }
})
<template>
  <button @click="handlerClick">按钮</button>
</template>
import Bus from "./Bus.js"
export default{
  methods:{
    handlerClick(){
      //自定义事件名 sendMsg
      Bus.$emit('sendMsg','这是向外部发送的数据');
    }
  }
}

//在需要接收外部事件的组件内
import Bus from "./Bus.js"
export default{
  mounted(){
    //监听事件的触发
    Bus.$on('sendMsg',data=>{
      console.log('这是接收到的数据',data);
    })
  }
  beforeDestoy(){
    //取消监听
    Bus.$off('sendMsg');
  }
}

用 $emit去监听,用$on去触发,注意需要$off来取消监听,否则可能会造成内存泄漏。

6.$attrs、$listener

适用于多级组件嵌套,但是不做中间处理的情况。比如祖先组件向孙子组件传递数据。

$attrs 可以获取父组件传进来,但是没有用props接收的属性。

可以通过v-bind="$attrs"传入内部组件。

搭配inheritAttrs使用,这个只是用来控制attrs是否在DOM中渲染。

//父组件
<child :title="title" :desc="desc"></child>

//子组件
<template>
    <div>
       <h2>{{title}}</h2>
     <p>{{$attrs.desc}}</p>
    </div>
</template>
<script>
export default {
  props:['title'],
  //
}
</script>

$listeners 包含父作用域中的(不包含.native的) v-on时间监听器。

可以通过v-on="$listeners"来传入内部组件。

7.Vuex 状态管理器

集中式存储管理所有组件的状态。

可以解决 多个视图依赖同一个状态 或者是 来自不同视图的行为需要变更同一个状态 的问题。

8.localStorage/sessionStorage

持久化存储。

 

posted @ 2022-07-19 15:06  时光独醒  阅读(31)  评论(0编辑  收藏  举报