JavaScript进阶(三十五):编译的准备工作

上篇博客,我们已经完成了最基本的抽象虚拟 DOM 树。所以接下来,我们剩下要做的事,就变的非常的简单了。

我们先把一些其他的东西来考虑考虑。

首先,现在我的这些节点,全是死的,这肯定不行呀。我需要做什么呀?我需要它们能够编译。

所以说白了,在我们的 VElement 这里,其实应该还有一级。

 

一般我们最上层是 VNode 节点,它实际上就是一个类型,没提供太多功能。

说白了,VNode 它主要是提供一个父类型用的,这样将来比较好判断,比如我看它是不是 instanceof VNode,就知道它是不是我的东西了。

 

然后这个 VText,其实也没太多东西可言,但是 VText,它要不要做到,把一个这样的东西:

"xyzqwe {{a+b}} fghdef" 给编译成 "xyzqwe 17 fghdef",如果 a=12,b=5 的话。

肯定是需要做到这一点的,所以 VText 它有简单的功能,就是一个编译。

 

以及还有一个 VElement,我希望它具有简单的编译功能。

比如我们加了个 :title="a",那么这时候它要给我编译成 title="12",以及这个 VElement,我不希望它具备复杂的功能,它就是一个,对这种普通的 HTML 元素的映射,这就够了。

为什么这样呢?原因很简单。

因为,一个类越大,越不好维护,而且性能也越低,所以我们让它单纯一点,它就只是描述一个节点,就够了。

 

而我个人更喜欢的是,在 VElement 这里在搞一级,我叫它 VComponent,就是一个组件了。

这个组件,它具备各种东西,比如它可以有各种各样的方法和数据。

那么这个怎么做呢?

首先,我们在加一个 js 文件,我叫它 VComponent.js:

我们希望的很简单,就是 VComponent,它上面有数据,有事件,有监听器,有 computed,等等,都是在它身上,它是一个带有功能的东西。

说白了,在 VElement 上面,它是不带数据的,什么都没有。

而 VComponent,才是我们真正要的东西。

 

然后这时候,我需要一个 options,因为它里面有各种各样的东西。

然后我具体怎么用它呢?大概这么来用,我希望是这样的:

那么接下来,我的 VComponent 这个东西,是不是应该继承自 VElement?

比如说,我这有一个普通的 vue 组件:

我们先不管 script 和 style 怎么写,我们写的 template,这个组件最终,我们要不要让它进到页面里面去?

肯定的,组件最终一定是要进到页面里面去的。

那大家有没有注意过一个事,就是我真的把这样一个组件,放到页面里之后,它有 template 这级吗?

没有。它留下的,只是 div 这一级。

换句话说,其实我的一个组件 VComponent,它到了最后,真正进到页面里面,表现出来的,也是一个元素。

 

所以我们就可以得出一结论:VComponent 是继承自 VElement 的,它也是一个元素。

而事实上,我们写起来的,也是这样,比方说我们假设有的 cmp 组件:

那这个 cmp 是元素吗?它也是。

所以 VComponent 应该是继承自 VElement 的,因为它也是一个元素。

 

那么到现在,别的先不管,既然是继承了,我们第一件事干啥?

super,一切继承,在根上都是 super:

因为你不用 super 的话,是没办法用 this 的。

super 完了之后,它才有 this 的。

 

然后接下来有个小问题,父级 super,它里面有啥参数?

我们都知道 VElement,它里面就一个参数,dom。

那这个是不是就对应于,我的那个 el:

但是在 VElement 那边,它是一个真 DOM。

而在我这边,它可能是个 DOM,也有可能是个选择器。

所以这里也要再来一次判断:

super 只要放在所有的 this 之前就可以了。

 

然后,我们需要考虑下,接下来要做点什么。

没别的,我们在 new VComponent 传的参数,得把它们给存起来:

首先,我们需要处理的是 el 和 data,这两个我们肯定是需要的。

但是我们需要做响应式,所以需要一个 proxy,并且需要它的 get,set:

set 设置完之后,我们是需要渲染的,既然说到渲染这个话题了,那么 VText 能不能渲染?能。

VText 的渲染,其实就是把这个文本里面,所夹带的数据,给它转换成一个真实的东西。

比如说,我在文本里面加一个 {{ a }},对于这来说,它应该替换成 12:

所以,VText 是要有 render 的。

以及 VElement 要不要渲染?肯定的,我们是需要把那一大堆 z- 开头的属性,给替换成真的,所以也需要渲染。

那既然如此,我们就可以直接在父级 VNode 里面放个 render:

当然,这个 VNode,其实我们并没打算真的让它去担任什么样的东西。

所以理论上它是不应该被渲染的,如果出现 VNode 被渲染的情况,其实是不对的。

所以这时候,如果你把一个抽象节点渲染出来了,我们就需要报错:

因为一旦执行到 VNode 身上的 render,就说明你某一级子类里面,没写东西,那就不对了。

所以,VText 需要 render,以及 VElement 和 VComponent 也需要 render:

接下来呢,这时候我们就需要触发自己的那个 render:

以及呢,这事还没完,前面的博客有说过,这样写 this 是不对的,所以我们需要在外面搞一层:

以及,还有一个 methods,我们也要把它存起来:

那么到这为止,该有的,一切都差不多了。

下篇博客,我们就需要开始做很多的事了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章