首先我们是需要成立标签类,这个类能让任何标签像我们之前普通 HTML 标签的元素一样最后挂載到我们的 DOM 树上。
它会包括以下要领:mountTo() —— 建设一个元素节点,用于后头挂載到 parent 父级节点上
setAttribute() —— 给元素挂上所有它的属性
appendChild() —— 给元素挂上所有它的子元素
首先我们来简朴实现我们 Div 类中的 mountTo 要领,这里我们还需要给他插手 setAttribute 和 appendChild 要领,因为在我们的 createElement 中有挂載属性子元素的逻辑,假如没有这两个要领就会报错。可是这个时候我们先不去实现这两个要领的逻辑,要领内容留空即可。
class Div { setAttribute() {} appendChild() {} mountTo(parent) { this.root = document.createElement('div'); parent.appendChild(this.root); } }
这内里其实很简朴首先给类中的 root 属性建设成一个 div 元素节点,然后把这个节点挂載到这个元素的父级。这个 parent 是以参数传入进来的。
然后我们就可以把我们本来的 body.appendChild 的代码改为利用 mountTo 要领来挂載我们的自界说元素类。
// document.body.appendChild(a); a.mountTo(document.body);
用此刻的代码,我们 webpack 打包看一下结果:
我们可以看到我们的 Div 自界说元素是有正确的被挂載到 body 之上。可是 Div 中的 span 标签都是没有被挂載上去的。假如我们想它与普通的 div 一样去事情的话,我们就需要去实现我们的 setAttribute 和 appendChild 逻辑。
接下来我们就一起来实验完成剩余的实现逻辑。在开始写 setAttribute 和 appendChild 之前,我们需要先给我们的 Div 类插手一个结构函数 constructor。在这里个内里我们就可以把元素建设好,而且署理到 root 上。
constructor() { this.root = document.createElement('div'); }
然后的 setAttribute 要领其实也很简朴,就是直接利用 this.root 然后挪用 DOM API 中的 setAttribute 就可以了。而 appendChild 也是同理。最后我们的代码就是如下:
class Div { // 结构函数 // 建设 DOM 节点 constructor() { this.root = document.createElement('div'); } // 挂載元素的属性 setAttribute(name, attribute) { this.root.setAttribute(name, attribute); } // 挂載元素子元素 appendChild(child) { this.root.appendChild(child); } // 挂載当前元素 mountTo(parent) { parent.appendChild(this.root); } }
我们 webpack 打包一下看看结果:
我们可以看到,div 和 span 都被乐成挂載到 body 上。也证明我们廉价的 div 也能正常事情了。
这里尚有一个问题,因为我们最后挪用的是 a.mountTo(),假如我们的 变量 a 不是一个自界说的元素,而是我们普通的 HTML 元素,这个时候他们身上是不会有 mountTo 这个要领的。
所以这里我们还需要给普通的元素加上一个 Wrapper 类,让他们可以保持我们元素类的尺度名目。也是所谓的尺度接口。
我们先写一个 ElementWrapper 类,这个类的内容其实与我们的 Div 是根基一致的。唯有两个区别
在建设 DOM 节点的时候,可以通过传当前元素名 type到我们的结构函数,而且用这个 type 去成立我们的 DOM 节点appendChild 就不能直接利用 this.root.appendChild,因为所有普通的标签都被改为我们的自界说类,所以 appendChild 的逻辑需要改为 child.mountTo(this.root)
class ElementWrapper { // 结构函数 // 建设 DOM 节点 constructor(type) { this.root = document.createElement(type); } // 挂載元素的属性 setAttribute(name, attribute) { this.root.setAttribute(name, attribute); } // 挂載元素子元素 appendChild(child) { child.mountTo(this.root); } // 挂載当前元素 mountTo(parent) { parent.appendChild(this.root); } } class Div { // 结构函数 // 建设 DOM 节点 constructor() { this.root = document.createElement('div'); } // 挂載元素的属性 setAttribute(name, attribute) { this.root.setAttribute(name, attribute); } // 挂載元素子元素 appendChild(child) { child.mountTo(this.root); } // 挂載当前元素 mountTo(parent) { parent.appendChild(this.root); } }
这里我们尚有一个问题,就是碰着文本节点的时候,是没有转换成我们的自界说类的。所以我们还需要写一个给文本节点,叫做 TextWrapper。
class TextWrapper { // 结构函数 // 建设 DOM 节点 constructor(content) { this.root = document.createTextNode(content); } // 挂載元素的属性 setAttribute(name, attribute) { this.root.setAttribute(name, attribute); } // 挂載元素子元素 appendChild(child) { child.mountTo(this.root); } // 挂載当前元素 mountTo(parent) { parent.appendChild(this.root); } }