相比于使用传统的Object实现补环境框架结构,使用 ES6 的 Class 具有以下优势:
以下是遵循跟浏览器保持一致的 document 继承结构
Object
└─ EventTarget
└─ Node
└─ Element
└─ HTMLElement
└─ HTMLDivElement
└─ ... (其他HTML元素)
└─ Document
└─ HTMLDocument
以下为框架代码的实现
class EventTarget {
// 所有能够监听和触发事件的对象的基类,为 DOM 中的各种元素(如 Node、Element、HTMLElement 等)提供了统一的事件处理接口,使得这些对象可以响应用户交互和其他事件
constructor () {
this.listeners = {}
}
addEventListener (type, callback) {
if (!this.listeners[type]) {
this.listeners[type] = []
}
this.listeners[type].push(callback)
}
removeEventListener (type, callback) {
if (!this.listeners[type]) return
const stack = this.listeners[type]
for (let i = 0; i < stack.length; i++) {
if (stack[i] === callback) {
stack.splice(i, 1)
return
}
}
}
dispatchEvent (event) {
if (!this.listeners[event.type]) return true
const stack = this.listeners[event.type].slice()
for (let i = 0; i < stack.length; i++) {
stack[i].call(this, event)
}
return !event.defaultPrevented
}
}
class Node extends EventTarget {
// 提供了基本的树结构操作和与节点相关的功能,所有的 DOM 元素和文本节点等都继承自Node
constructor () {
super()
}
}
class Element extends Node {
// 这个类里面放的是所有元素的Element类的属性方法和HTMLElement的属性方法,这里将 HTMLElement 的属性方法全部合并到Element中了
constructor () {
super()
}
}
class HTMLElement extends Element {
constructor () {
super()
}
}
// 一些内置的元素,比如div是来自于HTMLDivElement这个类实例化出来的
class HTMLDivElement extends HTMLElement {
constructor () {
super()
}
// 添加特有的属性和方法
}
// 一些自定义的元素名,他就会用HTMLUnknownElement这个类实例化出来
class HTMLUnknownElement extends HTMLElement {
constructor(tagName) {
super()
this.tagName = tagName
}
// 添加特有的属性和方法
}
class Document extends Node {
constructor () {
super()
}
createElement (tagName) {
switch (tagName.toLowerCase()) {
case 'div':
return new HTMLDivElement()
default:
return new HTMLUnknownElement(tagName)
}
}
}
class HTMLDocument extends Document {
constructor () {
super()
}
}
const document = new HTMLDocument()
console.log(document)