业务场景
注意到这句话是因为我在业务中遇上了点麻烦,类似上图,我有一个容器box组件,里面分为header和container,header可以通过label属性进行文字的定制,而container部分则放了个slot插槽标签,因此可在box标签体(以下简称标签体)内传入内容。现在的业务要求是,如果我给box组件传入hidden=“true”,并且标签体里面没有任何东西,则整个box组件都不显示(hidden默认为false,标签体没有数据时,box正常显示)。
为了实现这个效果,我在box组件最外层的div增加了一个v-if判断。如下图:
在App.vue中使用了该组件,代码如下:
初始化这个过程中没问题,问题在于当数据从有到无的时候,box组件并没有像预期的那样隐藏起来,而是依旧显示出来,只是container部分为空而已。如下图:
当我将box标签体内的水果种类从5个全部清空时,我们可以发现,按照我们的逻辑代码,此时的计算属性isShow应该是false,但是我们使用devtools跟踪的isShow却为true,而这也跟显示的结果一致,那么问题出在哪里呢?
插槽不是响应性的
上图是为我从vue官方截出来的,事实上我一开始也认为我的业务代码出现bug是因为这个。不过现在看来,按照官方的描述,其实我觉得插槽已经是响应式的了,因为当我减少一种水果甚至直接清空水果的时候,我传入box的默认插槽的数据已经发生变化,而组件也已经重新渲染了,难道这不是响应性吗?所以我猜测以前的插槽可能不支持这种响应,但是现在的插槽已经支持了。那么我的问题又为什么会出现呢?
计算属性有缓存机制
看到上述的小标题,相信你已经想到了什么。是的,计算属性是有缓存机制的。当我尝试不用计算属性,而是直接在div的判断(v-if="!!this.$slots.default || !this.hidden")或者通过方法返回值去判断时,都不存在这个问题。
总结
计算属性中有关插槽部分的计算是初始化组件的时候就决定了,插槽的使用情况的变化不会引起计算属性的重新计算,因此尽量别将插槽有关的判断放在计算属性中,即使要放入计算属性之中,也要确保插槽中的数据的变化不会影响到你的项目,这从某种意义上来讲,说“插槽不是响应性的”似乎也没问题。
写在最后: 码了整整一个晚上,不得不说,写博客真的很耗时间,但一想到如果有人因为看了我这篇帖子而发现项目中有关这方面的坑,那这一整晚就有价值了吧。以上就是自己的一点点浅见,如果有错误指出,请各位指正。