00:00
这节课我们来学习尝试书写diff更新子节点啊,尝试书写dif更新子节点,那为什么叫尝试书写地FF更新子节点呢?是因为我们这节课呢,要啊不撞南墙不回头的自己去写一写啊,就是咱们之前课程当中五角星,诶这个五角星当中的内容啊,我们要尝试更新这个子节点了,对吧?哎,那为什么叫尝试呢?因为这节课啊讲的这个东西到最后你会发现他没法落地。啊,为啥没法落地呢?咱们一边写啊一边说,我们先把测试用例写一下啊,你看新节点和老节点都是有children准的,我们现在先简单的来一下,比如说ul这边是力。好ABC啊,然后一会儿咱们可以把K加上啊。当然咱们现在key这个策略还没有写,不过很简单,这个key非常的简单啊,一会我们加上。好,ABC,然后接下来的话呢,呃,我们把这边也给它变成一个ul中的ABC。
01:06
好,那么你会发现这种情况是最复杂的。对吧,那这里头呢,其实就包括它可能会新增,它可能会删除,也可能会移动啊,移动现有节点,那么在这样的情况下呢,我们现在点击按钮是不变的啊,因为还没有写。啊,咱们说过还没有写,那么在这种情况下呢,我们又需要分类讨论,所以它比较复杂了,比较复杂的话呢,我们这个时候就把这个是同一个节点这一部分啊,那所有东西。哎,所有东西啊,把这一部分我们都拿出去。把这些东西拿出去,拿到一个新的函数中,咱们管它叫做patch v的这个。函数啊,叫patch not。点啊JS我们default。那么它为什么叫PA beno的呢?其实很简单呀,因为你要传两个节点,首先你要传新的啊,叫new b not,然后呢,你还要再去传一个呃,老的v not,所以叫old we not。
02:10
好,我们把这变成小写啊。那这样的话,大家可以看一下,就是我们刚才的代码呢,都直接写在这里头。哎,直接写到这里头啊,Expert default function这块要写个function。好,那这块就没了对吧?哎,这块就没了,这块就没了的话啊,为了验证它是好的啊,我们把这个改成123,那现在的话你看一点它不是没变化吗。对吧,哎,那是因为我们没引那个包。叫patch,所以patch它后边是PAVE的啊。好把这个。文件名也改成小写。I patno。啊,改成小写,改成小写怪怪的,那就小写吧,无所谓。好点JS,那所以说这块我们就需要把这两个参数传给那个函数。
03:03
他的目的呢,就是让代码更清晰。哎,一点它就OK了,但是还是报错啊,他说inner HTML of and范看看是怎么回事啊,29行。哎,这是old veno的,呃,Em。Oldnold的em。End它是安迪范。Old这块看一下。啊,它是报这个,它是报old be的,咱们看一下怎么回事啊。如果是同一个节点啊,同一个节点,那么我先要传O的new对吧,然后这边接的哦,这边接反了。是不是应该是先呕的再拗啊?哎,接反了啊,这回就字是能变的,发现了吗?这个字是能变的,但是还是那句话,咱们现在如果让这边变成这个啊,子节点和子节点它是变不了的。
04:03
对吧,哎,那所以说咱们现在就需要研究这块怎么写啊好了,那研究这块怎么写的话呢,其实这块又分为三种情况。啊,就是你更新子节点这块呢,又分为三种情况,那为了让你能听懂,其实它很简单,我们就把这个子节点呢拆出来啊,一条一条写在这上头。好,那这个就是老的,然后我们现在呢,在这边画条线。这个呢,就是新的。右边是新的啊,那老的呢,咱们现在能发现它就是ABC。诶,对不起啊,咱们这个key一直没处理,Key没处理的话,是在虚拟节点这个函数中,我们一直就没有处理,现在呢,到时候要给他处理了啊。这个key要给它处理掉对吧?哎,这个key,因为你这个data中如果有key就需要把它给拿出来啊,所以就是constant key。哎,就要看得塔中有没有K。
05:03
这能理解吧,对,那如果K是安迪范的话,那他呃,可能就是安迪范,我们要把这个key给拿上去。啊,这样的话,这个key就好被处理,所以他有一句话就处理成功了,哎,一句话我们把data中的这个key啊,Data中的这个key给他拿到,然后在这里补K,当然这个K可能是安迪范,那K就是安迪范呗。对吧,哎,K可能就是安范啊,这个K是安范是很正常的啊好了。那然后呢,咱们再看PPT啊,PPT咱们画一画,那现在的话你就明白了,就原来你现在要成ABC,那现在呢,它是不是有一种可能需要变成abcd呀。对吧,它需要变成abcd。这样的可能。那么这种可能的话,其实它是很简单的啊,为什么,为什么我能非常简单的判断出它能变成abcd,对,这就是因为我们只需要便利咱们的啊新节点,然后看看没有出现这个节点,那就说明它是新增的,那这个时候我就需要给他新增就可以了,对吧?哎,新增的情况。
06:10
我只需要一个一个便利,就是我在这儿便利便利便利便利对吧,便利如果然后便利每一个人的时候,我在看在老的当中。大家明白吗?没有没有我那是不是就说明我要新增了,对吧?哎,要新增了,那新增新增到哪里去。那比如说我现在AB,我我我现在给它变成ABCM。看见没有,把这个M插到C之前。那这个M要插在哪对,这个M是不是就要插在当前,你没有对吧?哎,你还没有处理的这个节点的前面。啊,就是你还没有处理的这个节点的子节点的前头啊,插在他前头就行。看懂了吗?那他当然,如果所有节点都处理掉了,那这个时候这个M就要插到最后边。
07:04
啊,什么意思呢?就是说我先判断A有好,B有M没有,那M没有的话,这个时候这个M要插在M的原来没有,那我这个M我要上数上到哪里。对,他就要上在所有的没有处理节点之前,那你就可能会问老师为什么不能说他能不能插在所有已经处理节点之后。啊,能不能处理所有已经节点之后,那不行。就是如果啊,如果你要把这个节点插在已经处理的节点之后啊,这两个是已经处理的,那这个时候万一我连续新增两个节点就乱了。比如这里再来个N,它就乱了。那你看它处理的时候,这个M它会创建在已处理的节点之后,对吧,但是这个N呢,会添加在已处理节点之后,那当前已处理是不是这两个节点,因为这个节点还没有算作被已处理,它在循环语句中是不影响那个I的那个指针的啊这个这个箭头是指的是那个循环变量I,循环变量I它不就是会从第一个儿子从下去进行一个变历吗?
08:09
这样子的对吧,哎,从这会进行一个便利,会进行便利便利便利这样子的啊,一个一个过程。对吧,所以一定要记住它如果要新增节点呢,那你现在是新创建的这个节点啊,新创建的这个节点去插入到所有已经处理的这个节点啊,啊所有啊错,所有未处理节点之前。哎,未处理节点之前,而不是所有已处理啊节点之后。啊,这个大家应该能听懂,因为AB它是处理了,处理了到这M插入在未处理节点前,N插入在未处理节点前,这样MN的顺序是对的。对吧,哎,你不能说,你不能说这个这个什么啊,你不能说他的之后,因为AB是处理的节点啊,那你可能特别疑惑,说老师你说的这是啥意思呀?哎,那咱们现在就去写写代码,你就明白了。
09:07
好,那咱们现在就真的把ABC变成ABCMN。事实胜于雄辩,我们来试一试。好,那这样的话点击没有用啊,因为我们在这是没有写的啊,派始B在这没有写,那怎么办呢?我们这个时候先去看新增的情况,对吧?诶那你说老师他不可能新增,有可能会那个什么,对,那我肯定要变利呀,对吧?哎,Light I等于零,然后I小于old的venode的啊哎,判断新的吧,New veno的children。的死。然后爱加加,好,我给它起一个名字叫CH,叫new啊,它的children的D项,这是CH对不对?好,那这个时候这个CH我们是不是就需要去寻找有没有同一个节点啊,就是用same meno的,所以这个KEY1定要加啊,因为你要不加K的话,这个时候如果都没有K的话,那这个时候是不是他就会无故判断他跟他是同一个节点。
10:06
明白吗?就即使这里头写了一个C。但是因为你没有加K,所以他就会认为这个力和这个力一样,K都是安迪范,他就认为他俩是同一个节点了。所以这个时候他就会把A更新为C了,他就不会再去做这种啊插入的操作了,大家一定要听懂,一定要加K啊,这个时候就揭示为什么K很关键了。对吧,所以这个时候呢,我们需要再次便利啊,就是看看有没有人key跟他一样,看看有没有人就是看看old的。这个v node中有没有节点K啊,就是和他。是same的。明白吗?Same的意思是什么?那就很简单,我们这时候要再遍历啊,For let go等于零,然后go小于old的veno的的lengths啊,Children的lengths,然后go加加,那这时候我们是不是要看,就如果old的we know的当中的Di对吧,哎,Di项。
11:05
啊,就是O勾项,这里是写成勾啊。好对吧,哎递勾项怎么着呢,对它的cell是完全等于你CH的啊cell的,并且呢,你O的v node的地勾项的这个cell啊key。也等于你CH的K,那么它们就是相同节点。对吧,那相同节点意义是什么?就意义是它们就处理完了,那处理完意思是什么?处理完就指的是,呃,对,就它处理完了,就这个节点我们就可以打一个标记啊,在他处理完了,那处理完其实什么都不用做。对吧?哎,什么都不用做,咱们就可以起一个呃,起一个标记,比如说light,呃,Is exist对吧?哎,咱们一开始认为false,然后你找到了,那它是不是就等于true啊。对吧,那是不是有的时候他是没有找到的。
12:00
这块能看懂吗?没有找到,就是我原来没有找到,那这个时候我是不是就可以输出啊,对吧?诶我把新节点输出吧。啊,我把这个new b的输出你就明白了,咱们看一下你看啊,我一点特别神奇一点。哎,报错26啊,这是哪错了,非exist找看一下啊。啊,这是勾打错了。好,你看我一点,诶还是报错。We not grow old we not children。啊,代码一多就容易懵啊,但是没关系,咱们看一下,你看一点它是不是输出了。对吧,哎,但他输出什么了,输出牛逼弄的不行,是不是输出这个牛逼的抽的第一项应该输出这一项,所以说你看一点是不是输出了,输出M和N了吧。发现了吗?输出MN了,那么M和N不重要,对M和N很重要,因为我们寻找到了就是哪些节点是需要更新的。
13:00
但是呢,最重要的那个值是这个I,是这个变量I,因为这个变量I指向谁了。变量I当前指向谁?咱们可以输出一下这个I,你看。点一下变量I是不是一个二一个三呀。对吧,那就相当于什么呢?相当于这是下标为第零项,这是下标为第一项,这是下标为第二项,那这个下标为第二项指的是什么?对,就是它老节点中它变量是它。啊,指他。对吧,就是下标为2A项嘛。这大家能理解吗?对吧,哎,就处理到这,那它为什么变成三了呢。为什么在这里这个I变成三了呢?因为他下一次循环的时候,是不是寻找到这个啊,寻找到你这个N了。对吧,哎,寻找到N了,所以说这个时候你你你可以便利,呃,咱们现在便利的是新节点。对吧,便利新节点,然后看看老节点当中有没有。啊,但是也可以说便利老节点,看看在新节点当中有没有,这都无所谓。就可以了,就是你就是要在old的你的那个呃,Children,就旧的子节点列表当中去寻找本次循环指向的一个新子节点。
14:07
对吧,哎,就可以了。啊就完事了,所以说这样的话,我们就可以插入到他之前的,这样的话我们就就做呗。那怎么做还是很简单的啊,还是很简单的,那就直接创建就行,创建的话不就是create吗。对吧,哎,所以说这个时候就create element,这是咱们之前课程写的,是不是直接把这C哎给创建出来是新的呀,就完事了,所以说这个呢,就叫do。啊,但是这个盗墓呢,现在给上树。这个do现在给上树啊,大家注意看。一点,这两个节点是不是给上树啊。没问题吧,哎,这两个节点给上述,并且你还要改变这个,呃,改变这个你这个节点的em啊,就应该等于这个do。还要上树,那上树怎么上树啊,对,是不是就直接让咱们老呃那个old veno的。
15:00
对吧,哎,Old windowno就直接啊喷啊,不是insert before要插在它之前啊,要不然顺序有问题了,对吧?哎,In before谁呢?是不是就插在咱们当前啊呃。这个把do插在当前处理的,那当前处理间你写个CH你试试对吧?哎,报错了啊,意思not f,因为是em对吧,M啊,地点还是报错。第二个词,这个有点问题了,应该就是old的veno中的第二项啊。爱children中的第二项,那那个。对吧,哎,Di项的erm这样写啊,一刷新这不就OK了吗。对吧,哎,一刷新这M就进了,但是N报错了,那这里报错的原因是什么呢?报错的原因呢,就是在这里呢,咱们啊搞错了一个概念。就是我们看图就知道了。这个I呢,表示的是我们便利啊,新的就改变后的啊,左边是老,这边是新,咱们给它加上这是旧。
16:05
哎的子节点子节点。好,然后右边呢,是新的字节点。现在我们的任务呢,就是这个I,它表示什么,你一定要想清楚,这个I表示的是啥嘞。大家想想,这个I表示的是什么呢?对,它表示的是便利新节点的这样的一个顺序,那么爱它会一一个一个的往前走啊。对吧,I一个一个的往前走,那M被插入进去之后,M会怎么样。大家想一想,对呀,M这个时候你看I现在不就等于二了吗?012,那这个时候它就会插在原来节点012。啊,插在插在原来节点012之前吗?那等于说这块你偷换了一个概念是不对的。零一二十二号之前等于说现在呢,咱就直接告诉你答案吧,就是我们现在呢,少用了一个指针。
17:01
啊,就是现在我们要去再来一个指针,这个指针指向所有没有处理的子节点的开头。懂了吧,所以这个UN啊,比如说叫安。UN不是表示否定吗?An啊,它就表示没有处理的,所以就是新创建的节点,新创建的节点是什么呢?就是你的new child。New new new not the children中的Di项。的em对吧,是不是要插入到所有未处理的节点,那所有的未处理节点是谁?对,就是old的window children的Du项的em。之前。这这块要少用一个指针。啊,这块是old。哎,而不是已处理节点了之后,因为插入已处理节点之后,M和N这个顺序会反啊,这个咱们都说过,咱们刚才讲过了。哎,所以就相当于你现在思路是A,现在被处理过了,因为我找到了,所以我就开始找他,然后。
18:02
UN就下移。明白吗?哎,然后呢,B我有匹配的啊,匹配的好了,那我就下移M我找到匹配的了,对吧?哎,M没找到匹配,对不起啊,所以M这个刚才B不是下移了吗?M就是找到B之后它也会下移啊,M没有匹配的,所以油温不动。就保证这个是没有处理的,一直是在他这儿看见了吗?保证是没有是一直在他这。所以这个代码呢,它就需要加入一个UN。啊,加入一个UN,那就相当于这个就是所有未处理的这个节点的开头,那这个的话,咱们比如说就管它叫UN啊,就等于一个零。那如果没有存在怎么样,存在了我们是不是可以让UN下移啊,对吧?哎,让处理的这个节点这个指针下移,那么如果是没存在,那节点指针不下移,对这块UN是不加加的。对吧,哎,那这个添加到不是老节点的children的em,是不是老节点的U啊em这样的话一加MN是不是进来了。
19:07
有没有发现是很开心的MN就进来了?但是有同学肯定会想到,如果最后我们加一个P。最后我们再来一个P,或者再来个Q,会不会报错呢?好,我们看一下一点果然报错了,对,这就是因为你UN已经到头了。对吧,哎,UN已经到头了,所以这个时候就直接就写判断,如果UN是小于你老节点的children的Les的啊,那这个时候是插入的。啊else是不是就直接在后边追加就可以了。对吧,哎,就直接在后边追加啊,Pen child就行。就完成了,把它给追加上,就不用插入之前了,这样是不是就MNPQ都加入了。发现了吗?对吧,这个MN和PQ就都加入了,是没有任何毛病的,对吧?哎,所以这个呢,就是咱们更新中的这个新建的一个小策略啊,更新中的一个新建的小策略,那这个时候可能大家想明没想明白一件事,就是说如果我现在交换位置呢,就是这个ABC。
20:12
它交换位置会怎么样,对吧,交换位置会怎么样,就是说我这个B,比如说我现在这个C挪到开头了。那这个时候你看我一点,他这个C没有多大开头。为啥?因为我现在在便利寻找,那那我便利寻找这个目的是什么,它是不是有两层目的,第一它是不是存在,第二它位置是不是一样,所以说咱们这块是不是就说当它不存在的时候怎么怎么样。这是它不存在的时候,对吧,那它存在的时候,它是不是还要判断位置是不是一样,就这个位置跟原来是不是一样,能理解了吗?所以说这个地方还要有事做,就是这个地方还有个事儿,因为这个地方你还要判断是不是移动节点。能理解吧,就这个地方,你还要判断移动节点,就是说它存在,但是位置不一样。
21:00
啊,那位置不一样,怎么判断呢?对呀,那就判断你当前的这个节点这个I和你这个节点这个勾是不是相同不就行了吗。对吧,哎,就行了。啊,那如果I不等于勾的时候,那这个时候就说明它移动位置了,但是你有没有发现移动位置的话,它就更复杂了。移动位置它就更复杂了,为什么?因为你移动位置的话,你有没有发现它就。就相当于什么,就相当于我我一移动位置的话,这个C,那我就相当于每次都要从头找。对吧,我每次都要从头找,就是我每找一个节点我都要从头找,我每找一个节点我都要从头找。啊,那你说我何苦呢?对吧,那你说我何苦呢?因为什么意思呢?这里咱们遇见的情况可能有三种啊,咱们重新讲一遍。第一种就是。老节点中没有的对吧,老节点当中没有的,我们这个时候是不是就需要给它创建出来啊,比如说MN啊,PQ啊都要创建出来,对吧?第二种就是老节点中啊,你这个新节点中删了,比如说把这个B删了。
22:04
那你就删。啊,咱们把这个PPT也做出来,这是新增的情况,然后第二种呢,是不是就是删除的情况。删除的情况,删除的情况呢,就是我这个AB。BA,对吧?C留着B没了。那这是不是就删除节点。对吧,那我现在如果我一次便利,我能把节点删吧,也能,咱不信咱把删除节点做一做啊,咱们这块可能有点小乱,大家见谅啊,因为这块你他必须是就是思维要很敏捷的啊,你看AB我要变成AC,那怎么办?啊,那现在一点没有没有作用了,因为咱们现在是不是这里没有这个能力,那现在的话AB点成AC什么什么意思,对,就是你这个节点,它新的这边怎么着没有遍历完,是不是这边还有UN。就是你便利,你看A便利A,你找到了便利C。便利C,你是不是你是不是找到了,但是这个UN指针你是下移,下移没有找到B,它是在下移对吧,但是呢,到最后没有处理的这个节点是不是还剩一个。
23:07
所以说你还得知道你最后剩的那一个是谁。能理解吗?那你这时候有可能会说,老师,我是不是要把没有处理的节点,我做成一个数组也可以。也可以就不用这个UN指针去指了。啊,不用这个U指针去指了,而是把没有处理的节点都设置成数组,也就相当于一上来就是这个数组。对吧,哎,然后呢,我处理完谁,我就把谁从数组中删掉,然后最后呢,那这样的话就很麻烦。这样的话就很麻烦,这是删除的情况,那是不是还有更新的情况。对吧,哎,更新的情况,比如说旧的是ABC,那么新的呢也是ABC。就是节点是没变化的,但是它更新了。对吧,比如说这个C更新了,它更新成了一个子节点,它里头有子节点了。啊,那更新,那你说老师更新不是很麻烦不麻烦,因为更新它的递归咱们已经写完了。
24:01
对吧,但是言外之意,我这里讲什么呢?就是大家觉得很乱,乱的原因是因为我们没有提供一个好的算法。能理解吗?我们没有,就是我们没有找到一个非常优秀的算法,就是你这种算法太落伍。啊,你这种算法太落伍了,这种算法不是最优的算法,或者换句话说,这种算法你把新增的,你把删除的,还有更新的你都。你都折在一起了,所以咱们刚才讲的这些呢,老师都可以给你打一个大大的叉。啊,老师都可以给他打一个大大的叉,哎,当然咱们可以把这个透明度降低一点啊,打个大大的叉。哎,为什么呢?因为你这个算法太太太弱。啊,算法太弱的话,意义是什么?目的就是出什么事了,对他是不是就会把更新新增还有删除是不是都会杂糅了。对吧,你给便利一趟,你你都很混乱,不知道哪些节点是新增的,哪些节点是啊是删除的,哪些节点是更新的,对吧,那怎么办?诶我们下个视频讲,我们下个视频呢,就要给大家介绍。
我来说两句