# 1、@Emit的实现原理

@Emit 装饰器是一个函数装饰器。 函数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

(target: any, propertyKey: string, descriptor: PropertyDescriptor)
1
  • target——对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • propertyKey——成员的名字(被修饰的方法的名字)。
  • descriptor——成员的属性描述符。

@Emit 装饰器的实现代码如下,主要分为以下几步:

  • 将事件名有小驼峰改为由 - 拼接。
  • 重写 由 @Emit 装饰器装饰的方法。
  • 在重写方法中调用 this.$emit(),同时将被装饰的函数的返回值作为参数传给 this.$emit()
export function emit(event: string){
    return function(target: Vue,propertyName: string,descriptor: PropertyDescriptor){
        //将changeName改为change-name
        const eventName=propertyName.replace(/\B([A-Z])/g, '-$1').toLowerCase();
        //触发的函数
        const originalFn=descriptor.value;
        //重写触发函数
        descriptor.value=function(this: Vue,...args: any[]){
          const emitFn=(returnValue: any)=>{
            //防止没有在@emit()中传递事件名称
            const emitName=event||eventName;
            returnValue?this.$emit.apply(this,[emitName,returnValue,...args]): this.$emit.apply(this,[emitName,...args])
          }
          //获取添加了@emit装饰器的返回值
          const returnValue=originalFn.apply(this,args)
          //触发this.$emit()
          emitFn(returnValue)
          // return returnValue;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 2、@Emit在Vue中的使用

import { Component, Prop, Vue} from 'vue-property-decorator';
import {emit} from "@/decorators/emit"
@Component
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;
  name='test';
  @emit('change')
  changeName(){
    this.name='james';
    return this.name;
  }
  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
Last Updated: 8/11/2020, 11:12:29 PM