Fork me on GitHub

vue 2.x 之子组件内调用父组件的方法

日常开发者经常会遇到多层级嵌套组件,并且需要在最里面的子组件触发最外面的父组件事件,这种情况下当然最好的做法其实还是使用Vuex进行管理,如果你的项目使用Vuex进行管理了,后面就没必要看了。Vuex的相关内容请自行百度查阅。

第一种:直接在子组件中通过this.$parent.event来调用父组件的方法
这种方式可以无限级别的向上找父级,例如:this.$parent.$parent.$parent.$parent.event,子组件也不需要props属性接收父组件的方法,但是多层级的时候容易搞乱层级,.$parent太多了

父组件

<template>
  <div>
    <child></child>
  </div>
</template>
<script>
  import child from '@/components/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('fatherMethod');
      }
    }
  };
</script>

子组件

<template>
  <div>
    <button @click="childMethod">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$parent.fatherMethod();
      }
    }
  };
</script>

第二种:父组件把方法传入子组件中,在子组件里直接调用这个方法
父组件内调用子组件的时候需要显示的传入方法(注意:这里是用的:传入方法),子组件还需要通过props接收父组件传来的方法,否则也不可以调用,另外就是多层级的时候需要一层一层的往下传,这时候就比较繁琐

父组件

<template>
  <div>
    <child :fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '@/components/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('fatherMethod');
      }
    }
  };
</script>

子组件

<template>
  <div>
    <button @click="childMethod">点击</button>
  </div>
</template>
<script>
  export default {
    props: {
      fatherMethod: {
        type: Function,
        default: null
      }
    },
    methods: {
      childMethod() {
        if (this.fatherMethod) {
          this.fatherMethod();
        }
      }
    }
  };
</script>

第三种:子组件里用$emit向父组件触发一个事件名(注意:这里是用的@传入方法),父组件监听这个事件名就行了,子组件不需要通过props接收父组件传来的方法,否则也不可以调用,这种最好向上传递一层父级,否则也需要层层传递

父组件

<template>
  <div>
    <child @fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '@/components/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('fatherMethod');
      }
    }
  };
</script>

子组件

<template>
  <div>
    <button @click="childMethod">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$emit('fatherMethod');
      }
    }
  };
</script>

第四种:使用$emit$on 配合传递事件
如果仅仅是父子一层,传递事件就使用第三种就可以了,如果多层传递或者是兄弟组件,还可以使用$emit$on 配合,其原理就是new 一个vue实例,然后在父子组件引入这个实例,这样在子组件触发的事件就会在父组件监听到了,这就是网上说的eventBus。

新建一个bus.js

import Vue from 'vue';
export default new Vue();

在父子组件分别引入这个bus.js

import eventBus from 'bus';

在子组件触发事件

  export default {
    methods: {
      childMethod() {
        eventBus.$emit('fatherMethod');
      }
    }
  };

在父组件监听事件

  export default {
    mounted() {
      //如果出现多次监听,肯定是没有解绑,可以在监听之前解绑,也可以在进入到这个路由或者渲染组件时候解绑一下就好了
      eventBus.$off('fatherMethod');
      eventBus.$on('fatherMethod', this.closeMenu);
    }
  };

当然如果你觉得建一个bus.js文件多余的话,可以在main.js里把bus加到原型上

//vue原型链挂载总线
Vue.prototype.eventBus = new Vue();

加到原型上的好处就是全局都可以使用了

// 广播事件 name
this.eventBus.$emit('name');
//解绑事件 name ,如果出现多次监听,肯定是没有解绑,可以在监听之前解绑,也可以在进入到这个路由或者渲染组件时候解绑一下就好了
this.eventBus.$off('name');
// 监听事件 name,并执行事件 this.closeMenu
this.eventBus.$on('name', this.closeMenu);

name : 只是一个标识,不需要是真实存在组件内的方法

posted @ 2019-09-21 17:41  较瘦  阅读(722)  评论(0编辑  收藏  举报
知识点文章整理