zoukankan      html  css  js  c++  java
  • 使用 TypeScript 自定义装饰器给类的属性增添监听器 Listener

    官网链接

    语法

    type PropertyDecorator =
      (target: Object, propertyKey: string | symbol) => void;
    

    target:直接写在类的属性上?

    看个例子:

    function capitalizeFirstLetter(str: string) {
      return str.charAt(0).toUpperCase() + str.slice(1);
    }
    
    function observable(target: any, key: string): any {
      // prop -> onPropChange
      const targetKey = "on" + capitalizeFirstLetter(key) + "Change";
    
      target[targetKey] =
        function (fn: (prev: any, next: any) => void) {
          let prev = this[key];
          Reflect.defineProperty(this, key, {
            set(next) {
              fn(prev, next);
              prev = next;
            }
          })
        };
    }
    
    class C {
      @observable
      foo = -1;
    
      @observable
      bar = "bar";
    }
    
    const c = new C();
    
    c.onFooChange((prev, next) => console.log(`prev: ${prev}, next: ${next}`))
    c.onBarChange((prev, next) => console.log(`prev: ${prev}, next: ${next}`))
    
    c.foo = 100; // -> prev: -1, next: 100
    c.foo = -3.14; // -> prev: 100, next: -3.14
    c.bar = "baz"; // -> prev: bar, next: baz
    c.bar = "sing"; // -> prev: baz, next: sing
    

    编译通不过:

    一种解决办法是,添加下图这种 dummy 方法,这种方法不推荐,因为缺乏灵活性:

    另一种方法较通用,即为类添加通用的所谓的 index signature:

    语法如下:

    意思是类 C 可以拥有任意的属性,且属性名称为 string

    运行时,target 的类型为类 C 的构造函数:

    key 为属性名:


    在下图第 15 行代码,直接给 C 的构造函数注入一个新的 on 监听函数:

    这个监听函数的函数体,直到代码44行 onXXX 被调用时才会被执行:

    给 C 对象实例的 foo 属性使用 Reflect.defineProperty API 设置一个 set 方法。

    这样,每次该实例的 foo 属性被修改时,就触发其 set 函数:

    在 set 函数实现体内,首先调用应用开发人员传入的 回调函数 fn,然后将 this[key] 设置为新的值 next.

    运行时,c.foo = 100, 会导致 Reflect.defineProperty 注册在 foo 属性的 set 方法被触发:

    在 set 函数里,我们再也不能访问到 C 实例的 foo 或者 bar 属性,但是通过闭包,能访问到其修改之前的原始值:

    更多Jerry的原创文章,尽在:"汪子熙":

  • 相关阅读:
    深入JAVA注解之属性注解
    深入JAVA注解之方法注解
    C# 启动外部程序的几种方法
    在.NET中实现彩色光标/动画光标和自定义光标[转]
    C#实现汉诺塔问题
    ExecuteNonQuery()返回值注意点
    在VS2012下不安装VS2010编译VS2010的工程
    Windows 窗体的.Net 框架绘图技术
    使用DataSet Datatable 更新数据库的三种方式
    C#.net 之货币转换
  • 原文地址:https://www.cnblogs.com/sap-jerry/p/14958479.html
Copyright © 2011-2022 走看看