00:00
这节课我们学习手写实现ast抽象语法数。那么我们首先说一下注意事项。首先呢,我们在学习源码的时候呢,一定要注意源码思想呢,要借鉴,但是绝对不要抄袭,我们一定要能够发现源码中啊书写的精彩的地方。第二呢,是要将独立的功能呢,能够拆解成为独立的JS文件中完成。通常啊,是一个独立的类,每个单独的功能呢,必须要能独立的单元测试。也就是说我们一会呢,将去使用vapa和vapa DV server啊来配合来进行一个模块化开发。第三呢,就是必须要围绕中心功能,先把主干完成,然后呢修剪枝叶。第四就是功能并不需要一步到位,功能的扩展啊,需要一步一步的完成,有的非核心功能呢,甚至不需要去实现。那么。
01:04
我们呢,这个呃,像ASD抽象语法数在VE源码,我给大家看一下啊。这个就是V2.6.12的一个源码,那么在这个源码当中呢,实际上啊,它就是啊,有特别多的部分在进行抽象语法数的一个,呃,一个转换,比如说我们可以去搜pass函数啊,诶这个pass函数呢,你看它这个注释就叫做convert HTML string to ast。啊,那它就是等于说把这个模板转换成ast,那么在pass函数当中呢,它最核心的呢,是调用了这个pass HTML函数。Pass HTML函数呢里面呢,就有这个while这个循环语句,并且还有我们刚刚学习过的这个stack站这个东西,对吧?诶stack咱们之前的课上已经学习并认识过他了,他的名字呢,就叫做站啊stack站对吧。
02:02
好,所以这样的话呢,你就呃能够呃知道我们练习它的目的呢,并不是说一五一十的把它都能写出来啊,因为这个里头呢,没有源码呢,是照顾了很多特别呃特别特别细枝末节的东西,比如说这个注释啊,多种注释。哎,然后还有比如说一些什么自封闭标签啊等等啊,各种复杂的情况他都考虑到了,但是我们呢,上课诶,我们只体现核心的算法啊,就只把主干完成,然后呢,我们的只做核心功能啊。好,我们介绍一下我们的开发环境,我们的开发环境呢,老师已经提前在这里给他列出来了。啊,这跟我们之前的V友源码系列课程的环境是类似的,我们来看一下。首先呢,我们的依赖呢,诶这里依赖bottom当然不要啊,这是咱们之前课程的老师直接给它啊,删掉好三个依赖,PA5 PES3 PA DV server3。
03:05
啊就可以了,那么va派DV server,呃,建议大家不要装四,Va派DV server最新版是四,但是呢,嗯,它确实跟外派五兼容程度不好,嗯,就是说它配置起来的话比较麻烦,所以还是用三就可以。我们看一下咱们的vapa的配置文件,就是挖派点conflict.js文件,这个文件当中你可以发现它非常的简单,我们就配置了入口啊,配置了出口。哎,配置了虚拟打包路径为虚拟打包的文件名,端口号,还有静态资源文件夹。所以我们的目的呢,就是要去打包src文件夹,打包到虚拟路径当中去。然后我们的index.html呢,就能够去引用这个虚拟路径。啊,他在这里就能够引用这个虚拟路径。没有问题啊。好,那么在这样的一个情况下,我们就可以进行一个模块化的一个开发了,我们可以起项目。
04:08
我们可以开始写啊CD好,那这个时候我们就n PM run一个DV。因为我们在这里身份证这是个DV啊,所以我们叫n PM run DV就可以了。好,然后接下来的话,我们就可以干嘛呢,接下来的话我们就可以去,嗯,打开8080端口。哎,8080端口呢,就开始运行了啊,我们不信你可以在这里alert一个123。啊,他这个都能弹出来。啊,没有任何问题,这就说明什么呢?说明我们模块化的这个环境已经配置好了。好,那我们就可以开始着手开发了,着手开发的话呢,我们就首先先来个模板字符串。
05:00
咱们叫templatet啊,或者叫template string,就是模板字符串,模板字符串我们用反引号,我们先用最简单的,所有的这个盒子呢,它的标签都没有类名啊,都不要把类名加上去,咱们用最简单的这个。哎,这种情况。好,然后呢,这里写个H3 h3写个你好,然后后边是ul。Ul里头呢,我们创建三个力标签。ABC。这里呢,老师要强调的是,我们创建的是字符串。那有的同学说,老师,我其实在写view的时候,我是写在template里面的。其实template里面的东西呢,也是字符串。只不过我们的编辑器呢,诶,它会自动识别template里面的元素,然后自动的呢,会把它这个颜色变成高光,我这里的颜色并没有变成高光色,就是并没有变成彩色的,这是因为我并没有保存成点view格式啊,比如说我现在在桌面上随便写一个点view。
06:12
诶好,那这里就变成了高亮色,但虽然这里的这个元HTML元素是高亮的,但是你千万不要认为这里面真的是盗墓啊,其实不是。我们的voe loader。就是view loader,大家在开发view的时候一定是安装过这个东西啊。view loader呢,实际上它的底层就是在用字符串的视角再看你书写的所有HTML标签。啊,老师再说一遍这句话,这句话很关键,就是你的viewe底层啊,它实际上啊,包括view view loader,它是在用字符串的视角啊,字符串的这样的一个视角,字符串的视角,大家一定要注意字符串的视角,然后是在做这个呃,字符串的视角,然后再去识别你写的所有东西,所以我们现在呢,把它自动写成字符串是合理的。
07:07
那我们现在的目的呢,其实就一件事,就是把这个模板字符串呢,能够变成抽象语法术。因为前文说过啊,咱们之前的课上都已经说过了,就是。抽象语法数的好处是什么?对,就是它能识别一些指令啊,当然识别指令不是我们这节课的事啊,我们这节课只形成抽象语法数啊,就是把呃抽象语法数识别出来,还有收大括号的标记啊,然后它呢,它的中点是生成模板啊,函数就是H函数,这样的话呢,方便咱们地步算法啊,方便咱们的那个最小量更新。所以这样的话呢,你就会发现一个非常重要的1HTIME类拼错了,非常重要的一个事情就是咱们的view啊,它底层啊,它是曲线救国的啊,就他的这个曲线救国的这种感觉是非常多的。啊,那么这里实际上就是一个曲线就国的感觉啊好,那我这块呢,就可以给他调用,那我可以可以给他pass出来。
08:04
哎,那这个东西呢,它就能得到as,我们再把这个as呢给输出。但是现在肯定会报错,为什么呢?因为你这个啊,对不起,这是pass函数啊,你这个pass函数是没有定义的。所以我们现在可以去定义这个pass函数,pass.js好,然后我们default这个function,这个函数呢,就是pass函数,Pass函数就是咱们的主函数。好,Part函数就是主函数的话呢,这块就接收一个就是template string。啊为参数,然后呢,它就可以返回啊,比如就返回它,那这样的话呢,不就呃控制台就能输出它,当然这会还没有引包,我们要引下包啊import pass from点杠pass.js。好,这样的话,我们就可以看见这个字符串就真的生成了,没有什么毛病啊,这个字符串就真的生成了。
09:00
那么现在的问题呢,就变得很简单了啊,也不是说简单,就是我们现在呢,就要开始啊,非常细致的去解决这个事情了,对吧?哎,非常细致的去解决这个就把它能变成抽象语法术的一个事情啊,那我们的核心要义是什么?核心要义就是要使用指针去一个字符一个字符的去遍历。对吧,一个字符一个字符的去便利它,然后呢,能够利用站的思想啊,能够收集这个div h3为什么要利用站的思想,原因其实很简单,这是因为这道题呢,非常像我们之前占的那道题目,我们之前占的这道题目不就是这道题目吗?这道题目呢,就是啊,老师给你分析这个重复多少倍,重复多少次的这个题目,那么在这个题目开始之前呢,老师就已经提示过大家一个词了,一句话叫做词法分析的时候啊,经常要利用占这个数据结构。啊,词法分析的时候呢,是经常是呃,要利用这个占这个数据结构,那么这里就有一个初学者的大坑啊,就站和递归非常像,所以说这块呢,其实就是咱们初学者的大坑。
10:11
什么大坑呢?就是我们再去分析这样的HTML字符串的时候,实际上到底是用力占还是字符串呢?答案就是占,因为对于字符串来说,词法分析最难的呢,就是要分析你这个标签的一个嵌套组合情况,那你说老师杠H3不就是杠H3的封闭标签吗?那这是一种特殊情况,那比如说这里又有div呢?比如说这里又有一个div标签。对吧,然后以至于这个div再套一个div标签,那都有可能。哈哈。所以在这种情况下,你这个地五标签的,嗯,你就要去用站这种思想来去啊,就是寻找每一个结束标签,它的对应的开始,它是封闭谁的对吧?哎,就这个杠div,它是封闭哪个div标签的,所以他这个事情呢,都是比较的,就是呃复杂,所以要利用站,我们现在呢,分析这一个HTML字符串,它的本质是什么,它的本质呢,就是我们要去模拟类似于浏览器编辑器啊,不是浏览器编辑器,我说错了哈,就是浏览器的内核要做的事情。
11:20
啊,浏览器内核要做什么事情,同学们对是不是要去进行这个标签的词法分析啊。所以这个时候我们这个指针呢,咱们就从上往下指啊,我们这个小指针它就要开始一个一个移动,那么它就要识别这个标签,如果你现在识别到这个标签是div标签呢,那他就要把div给进站。进这个div这个词就可以了,然后遇见H3呢,H3在进站。好。那么这个时候我之间遇见的不是很多文字吗?不就遇见了你好两个字吗?那你好这两个字实际上都是H3里的内容,所以这个时候我们是不是又可以去再做一个站来存储当前标签项里的内容啊?
12:05
这个大家有没有想明白,就是你要知道就这个这个H3这个你好,都是H3标签里面的内容。这个没有问题吧,所以这个时候的话,我们就可以再去,因为这个跟咱们刚才那道题是类似的。所以你好两个字进来了,好,那么遇见杠H3 h3出战,那你好也就跟着他跑了,那就说明H3里边是你好。大家发现了吗?所以那。那咱们再看看这种嵌套的形式,你看我们遇见ul了,那么ul了这个时候呢,就要去进展。好,Ul进站之后呢,这个时候就遇见力标签,遇见力标签之后呢,这个时候的话,我们就需要看见这块有个A,那这个时候字母A呢,就会进站。好,然后遇见杠力的话怎么办,这个力呢就出战,然后这个A呢就跟他跑了,就说明这个A呢和这个力呢,它是一对的。对吧,哎,就说明这个A是在这个力里边的,咱们这样内容呢,咱们现在是用绿颜色啊,绿颜色为底,然后标签咱们用蓝色。
13:08
是这样子的,然后同样的道理,这个时候呢,B又要进站,咱们大家注意看啊,这个时候B又要进站。啊。B又要进站对吧,哎,就这个,呃,这个这个这个这个这个B啊,但是这块要用绿颜色,所以这个时候你就会发现,实际上他也会新建一个力嘛,在这里。对吧,所以说这个利和弊到最后又跑了。好,然后力和C呢,其实也跑了。但是现在你会发现,就是这个ul,你有没有发现它没法统计这个ul,就是没法收纳他们三个了,就是ABC这三个字符串是能够呃特别准确的找到自己所在的力的,但是呢,我们的这个ul它没有这种收纳功能了。那么此时怎么办?对,此时就是我们之前这道算法题目呢?就是你每遍历一个开始,咱们这个时候是不是就需要来一个容器?
14:05
对吧。哎,每变了一个,然后要把空字符串压占呀,咱们之前不是说了吗?你看要把空字符串压占。所以现在的话,等于说我们现在要进的是什么?对,要进一个空的数组,要把这个数组东西给压占。那什么意思呢?也就相当于一上来是这个div,大家看见没有,那这个div的话,我们现在要干什么?对,我们现在就要在这里进一个新的容器。就是在这里要进一个新的容器,这个容器是什么?就是数组,因为JS当中容器无非就是对象和数组嘛,那这里数组是最方便的。啊,就是遇见一个新标签,我们就需要去创建一个数组在这边,那接下来呢,再遇见H3的话呢,H3进站。同样道理,我们在这边也要创建一个新数组。发现了吗?然后你好近战,哎,你好近战。啊,然后杠H3,这个时候H3出战,然后这个你好是不是就等于说是跟着H3的,就是你这个你好是跟这个H3的,然后这个你好H3的话,这个时候要干什么。
15:11
这个时候要干什么?对,这个时候这个容器不就是负责你好H3的吗。这能理解吗?因为你你这个容器实际上就相当于你好要进站的话,实际上是写在他这里头的。就说白了,就是写在他这里头的啊,那这里头就创建了一个文字,比如说这个文字呢,就叫做你好。对吧,哎,这个文字就叫做你好,然后这个你好的话怎么办?对他在出战的时候,这个时候是不是要做一个非常经典的操作,咱们在之前学那个案例的时候应该也知道了,就是这个数组是不是要与这个数组进行整合。没问题吧,对吧,就是说他要与他来进行整合。才行,这个大家应该能理解,所以说就相当于这个H3和这个你好都都已经进入到他的这个数组里了。明白吗?就他俩都已经进到这个数组容器中了,那进的时候进的是什么?进的是tag h3,然后内容是什么?
16:08
懂了吧,哎,所以他是这样子的,那所以这个时候你就明白了,为什么老师要在之前给大家储备一道题目。啊,就是为什么老师在之前要给你们储备一道,储备一道这个算法题啊,储备的这个算法题,其实对这个V友的这个底层,它是它是有啊有帮助的啊,他对你去理解这个view的这个底层,实际上是非常非常非常有帮助的,这个大家应该能理解。对吧,那继续,我们现在又遇见ul了,Ul进站,Ul进站之后呢,这块又要有一个数组。对吧,哎,又要一个数组,有个数组之后呢,遇见力力呢就进,然后这个力的时候又要需要创建一个数组,就每进一个标签就要进一个内容容器,然后这个时候这个A就进来了啊,这个A实际上就在这里头,那我们把这个A就直接放到这里头了啊,至于顶层就表示好,那遇见这个杠力的时候,那推怎么办?对,这个时候他肯定就会。
17:04
就会标记到它里头,对吧,什么叫标记,就是这个数组会以children准的形式写到这个力标签里头,然后这个时候这个力呢,实际上就会怎么样,是不是非常好,他就会出一层,因为这是ul的这个这个这个数组对吧,他就会把他自己是不是加到这个空里头去。那咱们现在可想而知,当这个B和C都落罗列过去之后,那这这几个东西是不是就相当于都已经啊,都被排排坐挪到了这个ul的这个小数组收纳数组当中啊,如果现在你听的有点不懂,那是因为你之前没有按照老师的要求把之前的算法储备那道题目写一遍啊,如果这个算法储备这道题目你写了一遍之后的话呢,那么这个题目实际上你是能显而易见的听懂的。好,那么当ul出战的时候,这个时候对它就没有了,它就没有的时候呢,这个时候它就会这ul也出战了,他是不是就会把这些在就是把ul跟它装一起,然后把ul是不是就会再去装到这个数组里头去。
18:09
明白了吗?所以就是相当于它是有从一两个占最后组建成一个数的结构,因为你到最后很明显这是树的第一个分叉,这是数的第二个分叉,这是树的第二个分叉的一根叉,两根叉,三根叉。发现了吗?那这个数本来就是一根叉两根叉三根叉,然后这里头也有三根叉嘛,对吧,那这个div实际上我们还没有做呢,因为我们还没做第三个div进站,然后又来个空数组,那这个空数组进站的话,跟着ul井水不犯河水,因为这UL已经出站了,对吧?诶放这,然后这里头又又放个div,所以这里又来个div,那这个div的话,实际上就又被引到了这个数组里头。然后这个div后面呢,又有个div,那这个div里头呢,就会有,哈哈。对吧,你看这里就会再有哈哈这个字样,没问题吧,那哈哈这个字样之后,随着他们出战之后,他不就连上了,那这个三棵树不就刚好大家注意看,这三棵树不就是非常满满的就出现了吗。
19:08
有没有发现对吧?这不就是三棵树,这不就是一个树的三棵树杈,这是老大对吧?这是老二,这是老三,对的,这里老大,老二和老三。没毛病吧?对吧,哎,对的,这里是老大老二和老三,老大老二和老三多简单,老大老二老三啊,所以到最后这个数呢,就相当于是在这。啊来给它构建出来的,也就相当于他这个算法,它需要有一个储备啊,如果这个算法你直接讲那是讲不懂的,哎,直接讲那是讲不懂的,他你需要有一个就之前这道题的储备就行啊,就现在的话,老师其实讲什么都是苍白的啊,就是如果说你之前这道智能重复这道题真真正正的好好听懂了,并且真的按老师的要求一五一十的写了,那么此时的你是不应该疑惑的。
20:00
啊,此时呢,你是不应该疑惑的啊,就是这个你是不会疑惑的好吧,哎,你肯定是能听懂的啊。好,那我们这节课就相当于把这个起步起好了,然后呢,也给你解释了,我们不会按那个事件钩子,因为事件钩子有点太麻烦了啊,然后咱们一会呢,就会按照咱们之前的逻辑来进行去写啊,其实你就把它当做一道算法题就行啊,不用把它想象的太难啊。
我来说两句