当在Vue组件中调用this. e m i t ( ) 时 , 实 际 上 是 调 用 了 ‘ V u e . p r o t o t y p e . emit()时,实际上是调用了 `Vue. prototype. emit()Vue.prototype.emit` 方法。
下面我们来看看Vue.$emit方法的定义

Vue.$emit 的方法源码位于 Vue源码目录下的src/core/instance/event.js

Vue.prototype.$emit = function (event: string): Component {
    const vm: Component = this
    if (process.env.NODE_ENV !== 'production') {
      const lowerCaseEvent = event.toLowerCase()
      if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
        tip(``)
      }
    }
    let cbs = vm._events[event]
    if (cbs) {
      cbs = cbs.length > 1 ? toArray(cbs) : cbs
      const args = toArray(arguments, 1)
      const info = `event handler for "${event}"`
      for (let i = 0, l = cbs.length; i < l; i++) {
        invokeWithErrorHandling(cbs[i], vm, args, vm, info)
      }
    }
    return vm
  }

从源码中可以看出$emit的执行是同步的,当 $emit执行之后会去遍历注册的事件数组

也就是说 this.$emit 之后的代码会在 $emit执行完成之后执行

那了解这个机制有什么用呢?可以用在什么地方呢?

答案是

可以用于子组件与父组件之间的联动也就是便于子组件实时获取父组件的数据,这个数据可通过Prop传递。

假设子组件中的this.$emit 执行之后要进行网络请求,这个网络请求依赖于父组件的中某个可变的数据或者依赖于父组件几个数据经过一定运算后得出的结果,这个时候就非常有用了。

你可能会说,这种情况可以通过提前把关联的变量都传给子组件来解决。这样是可以解决问题但是不够灵活,当你一个页面有几十个组件联动都有类似的需求后,这种方式就会变得非常的麻烦且很难维护。也有同学可能会说既让几十个组件都有需求那就直接用inject注入的方式来复制就好了,这种方式也可以但是组件的复用会变得麻烦,因为你需要在每个用到子组件的地方都注入数据。

下面我们用一个例子来演示这种情况。

  • 首先定义一个子组件
<template>
    <div class="child-container">
        <div>我是子组件</div>
        <div>子组件获取父组件数据进行列表展示</div>
        <button @click="onSearch">获取父组件参数后进行数据更新</button>
        <ul>
            <li v-for="(item,key) in list" :key="key">Hello{{key}}</li>
        </ul>
    </div>
</template>
<script>
    export default {
        name: "EmitComponent",
        props:{
            searchParam:{
                type:Object,
                default:()=>{}
            }
        },
        data(){
            return{
                list:[]
            }
        },
        methods:{
            onSearch(){
                this.$emit('getParam')
                if(this.searchParam.value === 10){
                    for (let i = 0; i < 10; i++) {
                        this.list.push(i)
                    }
                }else{
                    this.list.push(1)
                }
            }
        }

    }
</script>

在子组件中通过发送getParam 参数来获取父组件中传递的值来决定页面的展示当同步且正确的获取时,会展示10项列表数据,当获取失败时只展示1个

下面是父组件中的代码:

<template>
    <div>
        <div>$emit function 同步测试</div>
        <EmitComponent
            :search-param="childParam"
            @getParam="getParam"
        ></EmitComponent>
    </div>
</template>
<script>
    import EmitComponent from './_component/EmitComponent'
    export default {
        name: "TestEmit",
        components:{EmitComponent},
        data(){
            return{
                childParam:{
                    value:1
                }
            }
        },
        methods:{
            getParam(){
                this.childParam.value = 10
            }
        }
    }
</script>

父组件的逻辑很简单就是改变传给子组件Prop的值来模拟子组件从父组件获取指定运算数据的情况。

来看一下演示结果:
在这里插入图片描述
结果与预期的一致。

Logo

前往低代码交流专区

更多推荐