Vue计算出的属性未按我预期的那样重新计算

时间:2018-10-27 16:25:18

标签: vue.js vuejs2 vuex

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

使用下面的代码,为什么computed.filteredDocuments的值更改时this.searchCriteria不重新计算,我该如何调整代码以便在调用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>

1 个答案:

答案 0 :(得分:0)

我遇到的将您的示例代码转换成一段代码的问题是骆驼大小写/烤肉串大小写问题:HTML不区分大小写,因此该事件应该是kebab-case,而不是camelCase。本示例按预期进行过滤。

M+1
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);
          }
        }
      }
    }
  }
});