Vue.js 为什么我的方法会因为未知的原因而被调用?

Vue.js 为什么我的方法会因为未知的原因而被调用?,vue.js,Vue.js,我有一些函数filterData,可以根据多个输入更新图表数据。但是,当一个不相关的输入被更改时(比如在文本字段中键入),每次都会调用这些函数,从而导致图表被重新呈现。我已经记录了输出,所有参数均未更改 为什么要调用该函数?是否有任何方法可以跟踪它,或者我做错了 <DeviceChart :input-data="filterData(inputData, filters, otherParams)"/> 首先,一点背景知识 Vue模板将编译为渲染函数。当组件呈现时,调用此函数并返

我有一些函数
filterData
,可以根据多个输入更新图表数据。但是,当一个不相关的输入被更改时(比如在文本字段中键入),每次都会调用这些函数,从而导致图表被重新呈现。我已经记录了输出,所有参数均未更改

为什么要调用该函数?是否有任何方法可以跟踪它,或者我做错了

<DeviceChart :input-data="filterData(inputData, filters, otherParams)"/>

首先,一点背景知识

Vue模板将编译为
渲染
函数。当组件呈现时,调用此函数并返回VDOM节点树。这些VDOM节点描述子组件和相应的DOM。当组件随后更新时,将再次调用此
渲染
函数,返回新的VDOM树。Vue然后比较新旧树,并决定要进行哪些更改

您可以将
render
函数视为非常类似于计算属性。返回类型(VDOM节点树)对您来说可能有点陌生,但除此之外,它就像您自己编写的任何计算属性一样。它运行、跟踪依赖项并返回值。如果这些依赖项随后发生更改,它将再次运行

重要的是,与计算属性一样,Vue不知道如何准确地在该函数中使用依赖项。对依赖项的任何更改都将导致整个
render
函数重新运行

这听起来可能很贵,但通常不会造成很大的开销。比较VDOM节点的树通常也是一个相当便宜的操作。代价高昂的部分是更新DOM,无论使用什么方法,都必须这样做

因此,当您谈论“不相关的输入”更改时,您需要记住模板(即
render
函数)将始终作为一个整体运行。如果任何依赖项发生更改,则模板中的所有代码都将重新运行

在本例中,您有一个方法调用来过滤
输入数据的值。每次运行模板时都会调用它。输入和图表可能是模板中独立的组件,但这并不重要,整个模板需要运行以生成新的VDOM树。输入背后的数据是模板的依赖项,当它发生更改(由于输入的结果)时,模板将重新运行

但是,子组件不一定会重新渲染。当Vue比较父组件节点的VDOM树时,它会尝试将新旧树中的子节点配对(这就是
键的作用,以提供有关要配对的子节点的提示)。一旦它将孩子配对,它将为任何需要它的孩子更新道具。如果一个孩子的道具没有改变,那么这个孩子就不需要重新渲染自己

在您的例子中,我假设输入数据是一个数组。每次调用方法
filterData
时,它都会返回一个新数组。就您而言,数组可能是“相同的”,但实际上它不是相同的数组。从JavaScript
==
角度来看,该值已更改。我不知道DeviceChart对这些数据做了什么,但这很可能是导致它重新渲染的原因。对于Vue组件,重新渲染是一个便宜的过程,通常不值得担心,但您的图表可能正在使用某些第三方库,重新渲染可能不会那么简单

最简单的解决方案可能只是对
输入数据使用computed属性。在缓存计算属性时,每次运行模板时都会得到相同的数组。只有当计算函数的依赖项发生变化时,缓存才会失效,因此模板的其他依赖项不会产生任何影响

有许多选择,其中大多数是痛苦的。通常,这些操作包括将过滤后的值存储在
数据中
,并在需要时尝试对其进行更新。如果你能帮忙的话,我不建议你尝试那样的事情

如果你有一个循环,计算属性会变得很复杂


一个可行的、同样适用于循环的替代方法是为图表引入包装器组件。如果将
inputData
filters
otherParams
作为3个单独的道具传递给包装器组件,则执行实际过滤的责任可以转移到包装器组件中。只要这3个道具没有改变,当外部模板重新呈现时,包装器就不会被重新呈现。我仍然建议在包装器中使用computed属性,但这并不重要,因为模板无论如何都不会运行。

首先,介绍一点背景知识

Vue模板将编译为
渲染
函数。当组件呈现时,调用此函数并返回VDOM节点树。这些VDOM节点描述子组件和相应的DOM。当组件随后更新时,将再次调用此
渲染
函数,返回新的VDOM树。Vue然后比较新旧树,并决定要进行哪些更改

您可以将
render
函数视为非常类似于计算属性。返回类型(VDOM节点树)对您来说可能有点陌生,但除此之外,它就像您自己编写的任何计算属性一样。它运行、跟踪依赖项并返回值。如果这些依赖项随后发生更改,它将再次运行

重要的是,与计算属性一样,Vue不知道如何准确地在该函数中使用依赖项。对依赖项的任何更改都将导致整个
render
函数重新运行

这听起来可能很贵,但通常不会造成很大的开销。VDOM节点树的比较
export default {
  methods: {
    filterData(inputData, inputFilters, otherParameters) {
      console.log('Filter data has been called...')
      ...
      return result;
    }
  }
}