vue.js方法返回不断更新

时间:2019-02-04 19:12:21

标签: javascript vue.js

我是Vue js的新手,对不起这个愚蠢的问题。我正在使用v-data-table遍历数组。我需要方法的返回值不要改变,但是当方法运行时,它的每一行都会改变。

我尝试了计算值,但是由于某种原因您无法将变量传递到计算字段中?

<template>
  <div>
    <v-data-table
      :items="responseData"
      class="elevation-1"
    >
      <template slot="items" slot-scope="props">
        <td :key="props.item.tmdbId" class="text-xs-right">
          This: {{checkMovieExists(props.item.tmdbId)}}
        </td>
      </template>
    </v-data-table>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data() {
    return {
      allMovies: []
    };
  },
  mounted() {
    axios.get("XXXX")
      .then(response => (this.allMovies = response.data)) 
  },
  methods: {
    checkMovieExists(strMovieTmdbId){
      this.allMovies.forEach(movie => {
        if (movie.tmdbId == strMovieTmdbId) {
          return "Exists"
        }
      });                
    }
  }
}
</script>

1 个答案:

答案 0 :(得分:2)

计算的属性仅基于内部状态进行计算。它们的特殊之处在于,只要更改它们所依赖的内部状态,就必须重新计算它们。他们不接受任何参数,因为这将使他们更多地依赖于状态的反应性,从而破坏了这种缓存机制。您可以使用计算属性来处理从api获取的数据并对其进行循环,但是现在暂时忽略它。

如注释中所指出,方法的问题是您正在将forEach循环与一个函数一起使用,并返回内部函数。外部函数不返回任何内容,因此返回值为undefined。您可以通过多种方法来执行此操作,但是我认为使用Array.prototype.some最适合您的情况。您向该方法传递一个函数,该函数将针对您要对其调用的数组中的每个项目执行。如果这些调用中的任何一个返回true,则整个事件返回true,否则返回false

movieExists(strMovieTmdbId){
  return this.allMovies.some(movie => movie.tmdbId === strMovieTmdbId);
}

您会注意到我在这里返回一个布尔值。我这样做是因为您的函数称为XYZExists。我们可以使用此布尔响应在模板中输出适当的内容。

  <template slot="items" slot-scope="props">
    <td :key="props.item.tmdbId" class="text-xs-right">
      This: {{ checkMovieExists(props.item.tmdbId) ? 'Exists' : '' }}
    </td>
  </template>

就限定范围的插槽的使用而言,只要this.allMovies类似于:

[
  {
    tmdbId: 1
  },
  {
    tmdbId: 2
  }
]

请记住,items插槽会呈现整行,而不仅仅是一个单元格。您将需要用<tr> ... </tr>包围它。


正如下面的感谢评论所述,如果大量重新渲染模板,则使用此方法可能会导致性能问题。毕竟,每次调用该方法时,它都会针对该数组中的每个项目遍历整个数组。

相反,我们可以使用计算属性来准备数据。由于在挂接的挂钩中只分配一次数据,因此您的计算属性仅应计算一次。当然,您应该避免突变this.allMovies以防止重新计算您的计算属性。

您可以保留我们之前创建的方法,但是我们不会使用this.allMovies来呈现数据,而是将使用此方法来计算数据...一次。我们使用地图来创建一个额外的属性,其中包含方法的结果。

computed: {
  preparedData () {
    return this.responseData.map(
      row => {
        return {
          ...row,
          exists: this.movieExists(row.tmdbId)
        }
      }
    );
  }
}

现在,我们使用responseData而不是使用preparedData来渲染表。由于我们现在在每一行上都有一个预先计算的属性exists,因此我们只需检查props.item.exists即可,而不必调用函数。重新渲染模板后,只要responseData保持不变,我们就使用preparedData的缓存版本。

<v-data-table
  :items="preparedData"
  class="elevation-1"
>
  <template slot="items" slot-scope="props">
    <td :key="props.item.tmdbId" class="text-xs-right">
      This: {{ props.item.exists ? 'Exists' : '' }}
    </td>
  </template>
</v-data-table>