Вычисляемое свойство Vue не пересчитывается, как я ожидал - PullRequest
0 голосов
/ 27 октября 2018

Я пытаюсь создать общий компонент поиска с событием, которое отправляется со строкой поиска обратно к родителю, чтобы родитель мог фактически отфильтровать результаты.

С приведенным ниже кодом, почему 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 голосов
/ 27 октября 2018

То, с чем я столкнулся, превращая ваш пример кода во фрагмент, было одной из проблем, связанных с регистром верблюдов / кебабом: HTML не чувствителен к регистру, поэтому событие должно быть регистром кебаба, а не 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...