在某些情况下,Vue 的插槽会导致组件强制更新

前几天在给公司优化代码性能的时候发现 vue 插槽会导致组件强制更新,从而导致不必要的渲染,降低页面性能。

以下是我做的示例重现问题(只展示主要代码,省略样式等不必要的代码)。

首先我创建一个简单的组件 title-slot.vue,其中使用到了 <slot>,并添加的 updated 来监听组件是否更新,如果更新就会弹出对话框:

<template>

<h2>

<slot>this is second title</slot>

</h2>

</template>

<script>

export default {

name: "TitleSlot",

updated() {

alert('title slot component updated!')

}

}

</script>

然后我在 App.vue 中使用它,但不设定插槽内容:

<template>

<div id="app">

<h1>{{ count }}</h1>

<button @click="count += 1">click add count</button>

<title-slot></title-slot>

</div>

</template>

<script>

import TitleSlot from "./components/title-slot.vue"

export default {

name: 'App',

components: {

TitleSlot

},

data() {

return {

count: 0

}

}

}

</script>

不难看出 App.vue 中包含一个点击按钮更新 count 的功能,此时我们点击按钮更新并不会弹出对话框。
在某些情况下,Vue 的插槽会导致组件强制更新

但当在 App.vue 中设定 title-slot 组件的插槽内容后,再点击按钮更新 count,此时就会弹出对话框,也就是说 title-slot 组件更新了!

<template>

<div id="app">

<h1>{{ count }}</h1>

<button @click="count += 1">click add count</button>

<title-slot>this is second title(by slot)</title-slot>

</div>

</template>

在某些情况下,Vue 的插槽会导致组件强制更新

为什么会这样?经过搜索后发现了一片文章 请你说说 Vue 中 slot 和 slot-scope 的原理(2.6.11 深度解析) ,有对这部分内容进行讲解,对应内容是这样的:

其实,是因为执行 _t 函数时,全局的组件渲染上下文是 子组件,那么依赖收集自然也就是收集到 子组件的依赖了。所以在 msgInParent 更新后,其实是直接去触发子组件的重新渲染的,对比 2.5 的版本,这是一个优化。

虽然我不能完全理解其中的原理,但是可以感受到,我测试出来的这个行为在 vue 看来是正常的

真的是这样嘛?这样我可觉得太奇怪了,这样不就会造成很多不必要的渲染。

然后我又经过了尝试,发现了一个突破口: 在 App.vue 中用 v-slot 来使用插槽,这样再更新 count 的时候,title-slot 就不再更新了:

<template>

<div id="app">

<h1>{{ count }}</h1>

<button @click="count += 1">click add count</button>

<title-slot>

<template #default>

this is second title(by slot)

</template>

</title-slot>

</div>

</template>

在某些情况下,Vue 的插槽会导致组件强制更新

这究竟是为什么?不会真的要我在每个使用的地方都这样修改吧!

这里想问下大家有没有和我遇到一样的问题,大家都是怎么解决的呢,或者大家有看到介绍类似的文章,可以推荐一下吗,小弟不胜感激!

以上是 在某些情况下,Vue 的插槽会导致组件强制更新 的全部内容, 来源链接: utcz.com/p/935496.html

回到顶部