React基础(四):组件输出,为什么要用 key

上一篇博客中,我们讲过花括号 { },其实花括号 { } 不仅能输出数据,也能直接输出组件。

比如,我们一般写组件都是这样用的:

我们也可以把 Cmp1 这个组件,直接的放到一个变量里面:

并且,花括号 { } 不仅可以输出组件,还可以输出组件数组。

其实也非常的简单,首先我们要有一个数组,只不过它里面存的不是普通数据,而是组件:

首先,这种写法页面能出来,并没有问题。

但是控制台上面会有个警告。它说:在你这个数组里面的每一个子元素,必须得有一个 key 这个属性。

其实这个就涉及到了虚拟 DOM,我们在前面也描述过虚拟 DOM。如果你没接触过虚拟 DOM,就会感觉好高深,好厉害的样子。但如果你真正懂了,其实并不难,这里我们就用一张图来简单的理解:

所谓的虚拟 DOM,其实它是相对于真实 DOM 而言的。比如下图中,左边是 React,右边是真实的页面。

现在 React 中里面有一些数据,它里面存的就是虚拟 DOM,之前的博客也说过,虚拟 DOM 其实就是个 json。

然后它有一个 div,下面有三个 span。所以对应的,页面里面也是一样,因为虚拟 DOM 和真实 DOM 是一 一对应的。

我们在 React 里面去操作,其实操作的就是左边的 json。

但是现在有一个问题,就是右边页面里面的东西,不可能是永远静态的。

如果这个时候,我在左边新插入了一个 span。那是不是右边的真实 DOM 也得跟着变?

这个就是 React 里面虚拟 DOM 和真实 DOM 同步的问题。那么问题来了,就是同步的时候,不是你想象的那么简单。

我们先来看一个数组的例子:

比如我现在有一个数组: [12, 12, 5, 8 ]。删了一个 12,变成了:[ 12, 5, 8 ]。

那你能告诉我删的是哪个 12 吗?

再比如 [ 12, 5, 8 ] 变成了 [ 12, 9, 3 ],那你能告诉我它是怎么变过来的吗?

可能有人觉得是把 5,8 删完之后添加了 9,3。也有人觉得是把 5 改成 9,把 8 改成 3 了。也有可能是删了再添,添了在删等等各种各样的说法,这个根本没法说。

同样的,虚拟 DOM 也有这个问题。所以说虚拟 DOM 在实践当中有一个巨大的困难,就是需要跟踪左边的数据,以及右边它所对应的那个 DOM 标签。也就是左边的数据删了或者改了,右边对应的标签也要跟着删或者改。

所以,在虚拟 DOM 变化的过程当中,我们需要跟踪这个变化,然后需要同步的去调整真实的 DOM 节点。

那么有一种方法:你的数据只要跟之前不一样了,我就把所有的 DOM 节点全删了,然后再全都重新创建一遍。

这种方法肯定没问题,但是你觉得性能和效率如何?肯定是不行的。

那么在这个时候,它就必须得去想办法跟踪到底是谁变了,而 React 就是通过这个 key 来作为跟踪的一个依据。

简单的来说,key 是一个属性,它就像我们每个人的身份证一样,是独一无二的。

可以看到,加了 key 之后,它就不会报错了。

但是这里会有一个问题,你可能觉得奇怪:如果我这里不用数组,而是用三个变量会怎么样呢?

这个操作和上面的数组是差不多的,但是我没加 key,那为什么不报错呢?

为什么只有成组添加的时候需要用 key,而不成组就没有 key 的需求呢?

原因很简单,因为 React 其实可以自动的添加一个 key。

如果你用的是普通的单变量,一个一个的往里面插,那么你在插的过程当中,其实它就能跟踪你的这个变量,你的变量是谁它是知道的,所以它就能够准确的用这个 key 来表述出来。

但是如果成组的往里面插就不一样了。你这个数组,我是添了一个,还是删了一个,就没法说了,所以这个时候它就需要一个 key 的辅助。

所以用 key 需要注意三件事:

1,一个一个往里插没事,唯独是插数组的时候,就需要 key。这一点我们是必须要知道的。

2,key 值绝对不能重复。

3,key 值一定不能变。因为它本身就是依靠这个 key 来跟踪你的变化,如果你的 key 瞎变,那它就认为刚才那个 key 消失了,那个标签我就可以删了,这又多出来一个,我还要再新创建一个。所以如果这个 key 乱变,轻则影响性能,重则整个页面的 DOM 元素混乱。

然后我们继续:

刚才上面的写法其实不太好,因为我们很少会手动的去写一个数组,都是循环出来的。

那循环的应该怎么做呢,最先想到的肯定是 for 循环,那么我们来看下:

这样做是没问题的,但是也不太好。因为我们刚说过,key 是不能变的。

如果这个 arr 将来添加了一个东西:arr = [ 12, 11, 5, 8 ],就会导致 5 和 8 的 key 都变了。

所以说,用 index 作为 key 是非常不好的。

那么在开发中,这种 for 循环写起来太麻烦了,如果撇开 key,有没有简单一点的循环写法呢?

我们可以用 ES6 的 map。

可以看到,也能出来,并且没有报错。现在这种写法就比 for 循环要简单很多了。

其实我们还可以直接将 map 放到模板里面:

我们在项目中其实就是这么来写的。

但是这样写只有一行,都挤在一起不太容易看,并且也不好换行。

这里我个人有一个小习惯,就是在后面加一个括号 ( )

可以看到,这样写也是没问题的。

这里加的括号 ( ),其实和 return 里面括号意思是一样的。

这样的话,它里面的东西就可以随便换行,写起来,看起来也都方便一些。

所以,怎么让组件动态的加入进来,我们一般都是用 map 来做。

那么我们已经了解了组件如何输出,接下来我们就来看看组件如何去嵌套。

实际上来说,组件并没有什么特别的,它和 html 差不多,所以也可以和 html 一样来嵌套。

所以组件是可以嵌套着用的,并且实际开发中,我们也就是这么用的。

发布了78 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43921436/article/details/104197594