feng xiaohan

类(class)

类的类型(implement)

类的类型定义使用interface,然后类使用implements实现这个 interface:

interface Options {
  el: string | HTMLElement;
}
interface VueCls {
  options: Options;
  init(): void;
}

class Vue implements VueCls {
  options: Options;
  constructor(options: Options) {
    this.options = options;
  }
  init(): void {}
}
new Vue({
  el: "#app",
});

类的继承类型(extends)

使用 extends 继承某个类,继承之后就可以用 this 访问到被继承的类里的对象或方法。

// ...(省略上面一些接口的定义)
interface VNode {
  tag: string;
  text?: string;
  children?: VNode[];
}
class Dom {
  // 创建节点的方法
  createElement(el: string) {
    return document.createElement(el);
  }
  // 填充文本的方法
  setText(el: HTMLElement, text: string | null) {
    el.textContent = text;
  }
  // 渲染函数
  render(data: VNode) {
    let root = this.createElement(data.tag);
    if (data.children && Array.isArray(data.children)) {
      data.children.forEach((item) => {
        let child = this.render(item);
        root.appendChild(child);
      });
    } else {
      this.setText(root, data.text);
    }
    return root;
  }
}
class Vue extends Dom implements VueCls {
  options: Options;
  constructor(options: Options) {
    super(); // 继承类需要写 @1
    this.options = options;
    this.init();
  }
  init(): void {
    // 虚拟dom,通过js去渲染真实dom
    let data: VNode = {
      tag: "div",
      children: [
        {
          tag: "section",
          text: "我是子节点",
        },
        {
          tag: "section",
          text: "我是子节点2",
        },
      ],
    };
    let app =
      typeof this.options.el == "string"
        ? document.querySelector(this.oprions.el)
        : this.oprions.el;
    app.appendChild(this.render(data));
  }
}
new Vue({
  el: "#app",
});

@1:super()指向的是父类,相当于调用了父类的 prototype.constructor.call。它可以向父类传参。

readonly

只能添加在属性上,让属性只可读,不可以被修改

class Vue extends Dom implements VueCls {
    readonly options: Options;
       ...
}

private

添加在属性和方法上,被添加的属性和方法只能在其内部访问(不可在其子(继承类)或实例上访问)。

class Dom {
    // 创建节点的方法
    private createElement (el: string) {
        return document.createElement(el);
    }
    ...
}

protected

添加在属性和方法上,被添加的属性和方法只能在其内部或其子类内部访问(不可在其实例上访问)。

class Dom {
    // 创建节点的方法
    protected createElement (el: string) {
        return document.createElement(el);
    }
    ...
}

public

添加在属性和方法上,所有都能访问到。

所有属性和方法的默认值。

static

添加在属性和方法上,被添加的属性和方法只能访问到同 static 的属性和方法,只能在其实例上访问。

get 和 set

通过 get 和 set 来实现一个拦截器。

  • get:获取某个值时对其进行操作。
  • set:设置某个值时对其进行操作。
class Ref {
  _value: any;
  constructor(value: any) {
    this._value = value;
  }

  get value() {
    return this._value + "aaa";
  }
  set value(newVal) {
    this._value = newVal + "bbb";
  }
}
const ref = new Ref("哈哈");

console.log(ref.value); // 哈哈aaa

ref.value = "ccc";
console.log(ref.value); // cccbbbaaa

抽象类(abstract)

abstract定义的类为抽象类,abstract定义的方法为抽象方法。

  • 抽象类无法被实例化。
  • 抽象方法只能被描述,不能进行实现。
abstract class Vue {
  name: string;
  constructor(name?: string) {
    this.name = name;
  }
  getName(): string {
    return this.name;
  }
  abstract init(name: string): void; // 只能描述
}

抽象类如果要使用,可以使用extends继承,继承的类叫做派生类。派生类如果要继承抽象类,需要将抽象类里的抽象方法都实现

class React extends Vue {
  constructor() {
    super();
  }
  init(name: string) {} // 抽象方法必须实现
  setName(name: string) {
    this.name = name;
  }
}

派生类可以被实例化:

const react = new React();
react.setName("名字");

console.log(react.getName()); // 名字