链式调用与proxy

链式调用虽然快乐,可每个方法后面的 return this 略显繁琐与丑陋,括号与引号也未免太多。

例如下面这个简单的logger

new Logger()
  .addLabel("warn", "l4", "登录", "游客", "error")
  .addContent("失败")
  .addContent("密码不对")
  .end();

你可能已经对这样的封装习以为常了,但其实他还能这样写!

Log.warn.l4.label("登录", "游客").log("失败").error.密码不对;

我觉得后者有一种简洁美

具体实现如下

class Logger {
  label: string[] = [];
  content: unknown[] = [];
  addLabel(...label: string[]) {
    this.label.push(...label);
    return this;
  }
  addContent(content: unknown) {
    this.content.push(content);
    return this;
  }
  end() {
    // 做一些存储打印之类的操作
    console.log(this);
  }
}
function getLog() {
  const logger = new Logger();
  /** 访问链路 */
  const propertyLink: (string | number | symbol)[] = [];
  const self = (new Proxy(/** 目标不重要,因为实际上使用 target */ getLog, {
    get(target, property, receiver) {
      propertyLink.push(property);
      //   console.log(property);
      if (/** 表等级用 */ typeof property === "string" && /l\d+/.test(property)) {
        logger.addLabel(property);
      } else if (/** 直接添加标签 */ typeof property === "string" && ["warn", "error"].includes(property)) {
        logger.addLabel(property);
      } else if (/** 可以调用的方法 */ typeof property === "string" && ["log", "label"].includes(property)) {
        // 调用则添加内容
      } else {
        //over
        logger.addContent(property);
        return logger.end();
      }
      return self;
    },
    apply(target, thisArg, argumentsList) {
      const previousProperty = propertyLink[propertyLink.length - 1];
      if (previousProperty === "label") {
        logger.addLabel(...argumentsList);
      } else if (previousProperty === "log") {
        logger.addContent(argumentsList);
      }
      return self;
    },
  }) as any) as Log;
  return self;
}
const Log = new Proxy(getLog(), {
  get() {
    return getLog();
  },
});
type Log = {
  error: Log;
  warn: Log;
  info: Log;

  label: (...lables: string[]) => Log;

  l1: Log;
  l2: Log;
  l3: Log;
  l4: Log;
  l5: Log;
  l6: Log;
  l7: Log;
  l8: Log;
  l9: Log;
  /** 具体消息 */
  [k: string]: void | Log | any;

  log: (...arg: unknown[]) => Log;

  end: void;
};

Log.error.l9.错了呀;
Log.error.l9.warn.错了呀;
Log.error.l4.那天夕阳下的奔跑是我逝去的青春;

Log.warn.l4.log("有毒?").end;

Log.warn.l4
  .label("登录")
  .label("游客")
  .log("失败").end;

Log.warn.l4.label("登录", "游客").log("失败").error.密码不对;

new Logger()
  .addLabel("warn", "l4", "登录", "游客", "error")
  .addContent("失败")
  .addContent("密码不对")
  .end();

图片.png

你可能感兴趣的:(代理,链式方法)