【问题标题】:Vue computed property not recomputing as I would have expectedVue 计算属性没有像我预期的那样重新计算
【发布时间】:2018-10-27 16:25:17
【问题描述】:

我正在尝试创建一个通用搜索组件,该组件带有一个事件,该事件与搜索字符串一起发送回父级,以便父级实际上可以过滤结果。

使用下面的代码,当this.searchCriteria 的值发生变化时,为什么computed.filteredDocuments 不会重新计算?如何调整我的代码以便在调用updatedSearchString 时重新计算?

父组件

<template>
  <search :searchCriteria="searchCriteria" @searchString="updatedSearchString" />
  <div v-for="(doc, index) in filteredDocuments" v-bind:key="index">
    <div>{{doc.filename}}</div>
  </div>
</template>

<script>
import store from '../store/index'
import { mapState } from 'vuex'
// import _ from 'lodash'
import Search from '../components/search'

export default {
  name: 'Parent',
  components: {
    Search: Search
  },
  data () {
    return {
      searchCriteria: ''
    }
  },
  computed: {
    ...mapState({
      documents: state => state.documents.items
    }),
    filteredDocuments () {
      console.log('in computed')
      return _(this.documents)
        .filter(this.applySearchFilter)
        .value()
    }
  },
  methods: {
    updatedSearchString (searchString) {
      this.searchCriteria = searchString <-- I WOULD HAVE EXPECTED BY UPDATING THIS IT WOULD TRIGGER COMPUTED.FILTEREDDOCUMENTS TO RECOMPUTE
    }
  },
  applySearchFilter (doc) {
    console.log('in applySearchFilter')
    // If no search criteria return everything
    if (this.searchCriteria === null) {
      return true
    }

    if (doc.filename.toLowerCase().includes(this.searchCriteria.toLowerCase())) {
      return true
    }
    return false
  }
}
</script>

子组件

<template>
  <div>
    <q-search v-model="search" placeholder="Search" />
  </div>
</template>

<script>
export default {
  name: 'Search',
  props: {
    searchCriteria: { type: String, required: true }
  },
  data () {
    return {
      search: null
    }
  },
  mounted () {
    this.search = this.searchCriteria // Clone
  },
  watch: {
    search: function (newVal, oldVal) {
      // If no search criteria return everything
      if (!newVal) {
        this.clearSearch()
      }

      this.$emit('searchString', newVal) <-- THIS EMITS THE SEARCH VALUE TO THE PARENT
    }
  }
}
</script>

【问题讨论】:

  • filteredDocuments 不依赖于searchCriteria。只有过滤器回调函数是。
  • 但是由于filteredDocuments 使用this.applySearchFilter 的函数过滤,它使用this.searchCriteria,所以我希望它可以工作。当我在同一个组件中执行所有这些操作时,它会起作用。
  • 您不应该克隆数据。在子项中使用为 searchCriteria 计算的 settable。 setter 应该进行发射。这可能不是你麻烦的根源。我不知道为什么它不适合你。你有没有机会制作一个展示问题的小提琴?
  • 看起来applySearchFilter 不在您的methods 部分中。
  • @RoyJ 这完全是因为applySearchFilter 不在methods 中,正如您所指出的那样。

标签: vue.js vuejs2 vuex


【解决方案1】:

我将您的示例代码转换为 sn-p 时遇到了一些驼峰式大小写/kebab 大小写问题:HTML 不区分大小写,因此事件应该是 kebab-case,而不是 camelCase。此示例按预期过滤。

new Vue({
  el: '#app',
  data: {
    searchCriteria: '',
    documents: [{
        filename: 'FirstFile'
      },
      {
        filename: 'SecondFile'
      },
      {
        filename: 'LastOne'
      }

    ]
  },
  methods: {
    updatedSearchString(searchString) {
      this.searchCriteria = searchString
    },
    applySearchFilter(doc) {
      console.log('in applySearchFilter')
      // If no search criteria return everything
      if (this.searchCriteria === null) {
        return true
      }

      if (doc.filename.toLowerCase().includes(this.searchCriteria.toLowerCase())) {
        return true
      }
      return false
    }
  },
  computed: {
    filteredDocuments() {
      console.log('in computed')
      return this.documents
        .filter(this.applySearchFilter)
    }
  },
  components: {
    search: {
      template: '#child-template',
      props: {
        searchCriteria: {
          type: String,
          required: true
        }
      },
      computed: {
        search: {
          get() {
            return this.searchCriteria;
          },
          set(value) {
            this.$emit('search-string', value);
          }
        }
      }
    }
  }
});
<link href="https://unpkg.com/quasar-extras@latest/material-icons/material-icons.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/quasar-framework@latest/dist/umd/quasar.mat.min.css">
<script src="https://unpkg.com/quasar-framework@latest/dist/umd/quasar.mat.umd.min.js"></script>
<div id="app">
  <search :search-criteria="searchCriteria" @search-string="updatedSearchString"></search>
  <div v-for="(doc, index) in filteredDocuments" v-bind:key="index">
    <div>{{doc.filename}}</div>
  </div>
</div>

<template id="child-template">
  <div>
    <q-search v-model="search" placeholder="Search" />
  </div>
</template>

【讨论】:

猜你喜欢
  • 2019-10-25
  • 2018-03-05
  • 1970-01-01
  • 2021-12-17
  • 2020-11-27
  • 2020-12-01
  • 1970-01-01
  • 2020-02-03
  • 2019-10-03
相关资源
最近更新 更多