如果你是用 Vue 来开发项目的,那么,你曾经有可能访问slot.default()遇到如下问题:


(资料图片)

Slot "default" invoked outside of the render function:this will not track dependencies used in the slot. Invoke the slot function inside the render function instead.

本文本中,将会解释这个错误背后的原因以及如何解决这个问题。

插槽的调用需要发生在渲染函数或模板中。要抑制这个错误,我们只需要把代码移到一个计算的属性或从模板或渲染函数中调用的方法中。

“this will not track dependencies used in the slot” 指的是什么?

错误信息解释了问题产生的本质原因,但这个提示不是很清晰,无法帮助我们界定问题的本质。下面,我们来详细介绍下错误背后的原因产生。

this will not track dependencies used in the slot.

经过一些调查,我做了一个可复现的代码,并理解了在渲染函数之外使用slots.default()语法的含义。为了理解这个问题,我们先复习一下 Vue 的响应式原理。

Vue 的响应式性系统允许我们声明属性、数据和计算属性,而不需要跟踪它们的变化。响应式性系统在幕后工作,确保我们的变量始终是最新的。

在Vue框架内,最常见的响应式特征的情况是使用computed:

计算属性指的是一个变量,它可以被用来以有效和响应式的方式修改和操作你的组件中的数据和属性。

计算属性的一个简单例子是博客片段,我们把一篇完整的博客文章作为属性传递,并把它截断成一定数量的字符。另一个更常见的例子是一个简单的变量,用来定义一个按钮的文本,根据当前的状态 "显示 "或 "隐藏"。

举例来说,在 "expanded"的值被改变之前,下面的属性将永远不会再被运行。

const buttonText = computed( () => {  return expanded.value ? "Show less" : "Show more";});

除非expanded的值发生变化,否则上述方法不会再被触发。Vue 在幕后所做的观察expanded变量的工作就是所谓的 "跟踪依赖性"。

你可能已经意识到了,"跟踪依赖" 这几个字和Vue框架在试图访问插槽时产生的错误中提到的一样。事实上,这个错误是为了告诉我们,在渲染函数之外使用slots.default()的语法,会使变量失去响应性,因此它不会 "跟踪" 任何可能影响它的变化。

拿上面的例子来说,失去依赖关系的跟踪将意味着无论expanded的值是多少,按钮都不会改变。

// 下面的代码只是为了说明问题//  我们只是假设了一个具有跟踪依赖性的变量,这也是我们插槽发生的情况const expanded = ref( false ); //Broken Trackingconsole.log(buttonText)// 输出 "Show more"expanded.value = true;console.log(buttonText)// 输出: "Show more"  值没有没有改变,因为Vue无法跟踪 expanded 的变化。

在我们的代码库中,未被追踪的变量不是我们想要的东西,应该要尽量的避免它。

如何确保 Vue 插槽被跟踪依赖

接下来,我们分析下可以做些什么来确保我们的插槽有一个响应式的跟踪系统,确保不会更新失败

通过确保我们的槽调用发生在渲染函数和模板中,问题就可以解决了,正如错误信息中提到的那样。

Invoke the slot function inside the render function

我们现在要介绍两种不同的情况。第一种是在使用渲染函数时调用插槽函数,第二种是在使用vue单文件组件的