使用JSX 建立组件 Parser(解析器)开发的示例(6)

首先我们来简单实现以下我们 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 打包看一下效果:

使用JSX 建立组件 Parser(解析器)开发的示例

我们可以看到我们的 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 打包一下看看效果:

使用JSX 建立组件 Parser(解析器)开发的示例

我们可以看到,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); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsddys.html